From 01ac3d9ca2359d5e5828da224d29866c3d5038cc Mon Sep 17 00:00:00 2001 From: southeo Date: Tue, 12 Dec 2023 13:25:22 +0100 Subject: [PATCH 1/3] Upsert specimens --- .../objects/DigitalSpecimenUpdateWrapper.java | 8 ++ .../ProcessedDigitalSpecimenRequest.java | 10 ++ .../handlemanager/service/DoiService.java | 5 +- .../handlemanager/service/HandleService.java | 5 +- .../handlemanager/service/PidService.java | 114 +++++++++++++----- .../service/HandleServiceTest.java | 61 ++++++++-- 6 files changed, 164 insertions(+), 39 deletions(-) create mode 100644 src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/DigitalSpecimenUpdateWrapper.java create mode 100644 src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/ProcessedDigitalSpecimenRequest.java diff --git a/src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/DigitalSpecimenUpdateWrapper.java b/src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/DigitalSpecimenUpdateWrapper.java new file mode 100644 index 00000000..8db0a48d --- /dev/null +++ b/src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/DigitalSpecimenUpdateWrapper.java @@ -0,0 +1,8 @@ +package eu.dissco.core.handlemanager.domain.requests.objects; + +public record DigitalSpecimenUpdateWrapper( + String handle, + DigitalSpecimenRequest digitalSpecimenRequest +) { + +} diff --git a/src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/ProcessedDigitalSpecimenRequest.java b/src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/ProcessedDigitalSpecimenRequest.java new file mode 100644 index 00000000..27473597 --- /dev/null +++ b/src/main/java/eu/dissco/core/handlemanager/domain/requests/objects/ProcessedDigitalSpecimenRequest.java @@ -0,0 +1,10 @@ +package eu.dissco.core.handlemanager.domain.requests.objects; + +import java.util.List; + +public record ProcessedDigitalSpecimenRequest( + List newRequests, + List updateRequests +) { + +} diff --git a/src/main/java/eu/dissco/core/handlemanager/service/DoiService.java b/src/main/java/eu/dissco/core/handlemanager/service/DoiService.java index c6aab982..052fa69c 100644 --- a/src/main/java/eu/dissco/core/handlemanager/service/DoiService.java +++ b/src/main/java/eu/dissco/core/handlemanager/service/DoiService.java @@ -50,8 +50,9 @@ public JsonApiWrapperWrite createRecords(List requests) List handleAttributes; try { switch (type) { - case DIGITAL_SPECIMEN -> - handleAttributes = createDigitalSpecimen(requestAttributes, handles); + case DIGITAL_SPECIMEN -> { + return upsertDigitalSpecimen(requestAttributes, handles); + } case MEDIA_OBJECT -> handleAttributes = createMediaObject(requestAttributes, handles); default -> throw new UnsupportedOperationException( type + " is not an appropriate Type for DOI endpoint."); diff --git a/src/main/java/eu/dissco/core/handlemanager/service/HandleService.java b/src/main/java/eu/dissco/core/handlemanager/service/HandleService.java index 6de07285..ded0a89b 100644 --- a/src/main/java/eu/dissco/core/handlemanager/service/HandleService.java +++ b/src/main/java/eu/dissco/core/handlemanager/service/HandleService.java @@ -53,8 +53,9 @@ public JsonApiWrapperWrite createRecords(List requests) try { switch (type) { case ANNOTATION -> handleAttributes = createAnnotation(requestAttributes, handles); - case DIGITAL_SPECIMEN -> - handleAttributes = createDigitalSpecimen(requestAttributes, handles); + case DIGITAL_SPECIMEN -> { + return upsertDigitalSpecimen(requestAttributes, handles); + } case DOI -> handleAttributes = createDoi(requestAttributes, handles); case HANDLE -> handleAttributes = createHandle(requestAttributes, handles); case MAPPING -> handleAttributes = createMapping(requestAttributes, handles); diff --git a/src/main/java/eu/dissco/core/handlemanager/service/PidService.java b/src/main/java/eu/dissco/core/handlemanager/service/PidService.java index b3272e19..a1b2abc6 100644 --- a/src/main/java/eu/dissco/core/handlemanager/service/PidService.java +++ b/src/main/java/eu/dissco/core/handlemanager/service/PidService.java @@ -27,7 +27,9 @@ import eu.dissco.core.handlemanager.domain.jsonapi.JsonApiWrapperWrite; import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute; import eu.dissco.core.handlemanager.domain.requests.objects.DigitalSpecimenRequest; +import eu.dissco.core.handlemanager.domain.requests.objects.DigitalSpecimenUpdateWrapper; import eu.dissco.core.handlemanager.domain.requests.objects.MediaObjectRequest; +import eu.dissco.core.handlemanager.domain.requests.objects.ProcessedDigitalSpecimenRequest; import eu.dissco.core.handlemanager.domain.requests.vocabulary.specimen.ObjectType; import eu.dissco.core.handlemanager.exceptions.InvalidRequestException; import eu.dissco.core.handlemanager.exceptions.PidCreationException; @@ -38,7 +40,7 @@ import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -280,36 +282,96 @@ protected ObjectType getObjectType(List requests) { return ObjectType.fromString(type.get()); } - protected ArrayList createDigitalSpecimen(List requestAttributes, + protected JsonApiWrapperWrite upsertDigitalSpecimen(List requestAttributes, Iterator handleIterator) - throws InvalidRequestException, JsonProcessingException, PidResolutionException { - var handleAttributes = new ArrayList(); - var physicalIds = new ArrayList(); + throws InvalidRequestException, JsonProcessingException, PidResolutionException, PidCreationException { + var specimenRequests = new ArrayList(); for (var request : requestAttributes) { + specimenRequests.add(mapper.treeToValue(request, DigitalSpecimenRequest.class)); + } + var processResult = processSpecimenRequests(specimenRequests); + var recordTimeStamp = Instant.now().getEpochSecond(); + var pidAttributes = createNewDigitalSpecimenRecords(processResult.newRequests(), handleIterator, + recordTimeStamp); + pidAttributes.addAll(updateDigitalSpecimen(processResult.updateRequests(), recordTimeStamp)); + return new JsonApiWrapperWrite(formatCreateRecordsSpecimen(mapRecords(pidAttributes))); + } + + private ArrayList createNewDigitalSpecimenRecords( + List specimenRequests, Iterator handleIterator, + long recordTimestamp) + throws PidResolutionException, InvalidRequestException, PidCreationException { + if (specimenRequests.isEmpty()) { + return new ArrayList<>(); + } + var handleAttributes = new ArrayList(); + for (var request : specimenRequests) { var thisHandle = handleIterator.next(); - var requestObject = mapper.treeToValue(request, DigitalSpecimenRequest.class); - physicalIds.add( - requestObject.getNormalisedPrimarySpecimenObjectId().getBytes(StandardCharsets.UTF_8)); handleAttributes.addAll( - fdoRecordService.prepareDigitalSpecimenRecordAttributes(requestObject, thisHandle)); + fdoRecordService.prepareDigitalSpecimenRecordAttributes(request, thisHandle)); } - verifyNoRegisteredSpecimens(physicalIds); + log.info("Posting {} new digital specimen fdo records to db", specimenRequests.size()); + pidRepository.postAttributesToDb(recordTimestamp, handleAttributes); return handleAttributes; } - protected void verifyNoRegisteredSpecimens(List physicalIds) - throws PidResolutionException { - var registeredRows = pidRepository.searchByNormalisedPhysicalIdentifier( + protected List updateDigitalSpecimen( + List updateRequests, long recordTimestamp) + throws InvalidRequestException, PidResolutionException { + if (updateRequests.isEmpty()) { + return Collections.emptyList(); + } + List> attributesToUpdate = new ArrayList<>(); + List flatList = new ArrayList<>(); + for (var request : updateRequests) { + var requestAttributes = mapper.valueToTree(request.digitalSpecimenRequest()); + flatList.addAll(fdoRecordService.prepareUpdateAttributes( + request.handle().getBytes(StandardCharsets.UTF_8), requestAttributes, DIGITAL_SPECIMEN)); + attributesToUpdate.add(flatList); + } + log.info("Updating {} digital specimen fdo records to db", updateRequests.size()); + pidRepository.updateRecordBatch(recordTimestamp, attributesToUpdate, true); + return flatList; + } + + private ProcessedDigitalSpecimenRequest processSpecimenRequests( + ArrayList specimenRequests) { + var physicalIds = specimenRequests.stream() + .map(request -> request.getNormalisedPrimarySpecimenObjectId().getBytes( + StandardCharsets.UTF_8)).toList(); + var registeredPhysicalIdentifiers = pidRepository.searchByNormalisedPhysicalIdentifier( physicalIds); - if (!registeredRows.isEmpty()) { - var registeredHandles = registeredRows.stream() - .map(row -> new String(row.getHandle(), StandardCharsets.UTF_8)).toList(); - log.error("Attempting to register identifiers for existing records"); - log.debug("Handles already registered: {}", registeredHandles); - throw new PidResolutionException( - "Unable to create PID records. Some requested records are already registered. Verify the following digital specimens:" - + registeredHandles); + var registeredPhysicalIdentiferMap = registeredPhysicalIdentifiers.stream() + .collect(Collectors.toMap(row -> new String(row.getData(), StandardCharsets.UTF_8), + row -> new String(row.getHandle(), StandardCharsets.UTF_8))); + var writableHandles = pidRepository.checkHandlesWritable( + registeredPhysicalIdentiferMap.values().stream().map(s -> s.getBytes( + StandardCharsets.UTF_8)).toList()).stream() + .map(h -> new String(h, StandardCharsets.UTF_8)).collect(Collectors.toSet()); + var updates = specimenRequests.stream() + .filter(request -> requestExistsAndIsWriteable(request, registeredPhysicalIdentiferMap, + writableHandles)) + .map(request -> new DigitalSpecimenUpdateWrapper( + registeredPhysicalIdentiferMap.get(request.getNormalisedPrimarySpecimenObjectId()), + request + )) + .toList(); + if (!updates.isEmpty()) { + log.debug("Existing records: {}", + updates.stream().map(DigitalSpecimenUpdateWrapper::handle).toList()); } + specimenRequests.removeAll( + updates.stream().map(DigitalSpecimenUpdateWrapper::digitalSpecimenRequest).toList()); + + return new ProcessedDigitalSpecimenRequest(specimenRequests, updates); + } + + private boolean requestExistsAndIsWriteable(DigitalSpecimenRequest request, + Map registeredPhysicalIdentifiers, Set writableHandles) { + return registeredPhysicalIdentifiers.containsKey(request.getNormalisedPrimarySpecimenObjectId()) + && + writableHandles.contains( + registeredPhysicalIdentifiers.get(request.getNormalisedPrimarySpecimenObjectId())); } protected List createMediaObject(List requestAttributes, @@ -332,14 +394,13 @@ public JsonApiWrapperWrite updateRecords(List requests, var recordTimestamp = Instant.now().getEpochSecond(); List handles = new ArrayList<>(); List> attributesToUpdate = new ArrayList<>(); - Map recordTypes = new HashMap<>(); + var recordType = getObjectType(requests); for (JsonNode root : requests) { JsonNode data = root.get(NODE_DATA); byte[] handle = data.get(NODE_ID).asText().getBytes(StandardCharsets.UTF_8); handles.add(handle); JsonNode requestAttributes = data.get(NODE_ATTRIBUTES); ObjectType type = ObjectType.fromString(data.get(NODE_TYPE).asText()); - recordTypes.put(new String(handle, StandardCharsets.UTF_8), type); var attributes = fdoRecordService.prepareUpdateAttributes(handle, requestAttributes, type); attributesToUpdate.add(attributes); } @@ -347,7 +408,7 @@ public JsonApiWrapperWrite updateRecords(List requests, checkHandlesWritable(handles); pidRepository.updateRecordBatch(recordTimestamp, attributesToUpdate, incrementVersion); - return formatUpdates(attributesToUpdate, recordTypes); + return formatUpdates(attributesToUpdate, recordType); } protected void checkInternalDuplicates(List handles) throws InvalidRequestException { @@ -375,13 +436,12 @@ private Set findDuplicates(List handles, Set handlesToUp } protected JsonApiWrapperWrite formatUpdates(List> updatedRecords, - Map recordTypes) { + ObjectType type) { List dataList = new ArrayList<>(); for (var updatedRecord : updatedRecords) { String handle = new String(updatedRecord.get(0).getHandle(), StandardCharsets.UTF_8); var attributeNode = jsonFormatSingleRecord(updatedRecord); - var type = recordTypes.get(handle).toString(); - dataList.add(new JsonApiDataLinks(handle, type, attributeNode, + dataList.add(new JsonApiDataLinks(handle, type.toString(), attributeNode, new JsonApiLinks(profileProperties.getDomain() + handle))); } return new JsonApiWrapperWrite(dataList); diff --git a/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java b/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java index c42314a6..f967a676 100644 --- a/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java +++ b/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java @@ -64,6 +64,7 @@ import com.fasterxml.jackson.databind.JsonNode; import eu.dissco.core.handlemanager.Profiles; +import eu.dissco.core.handlemanager.domain.FdoProfile; import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute; import eu.dissco.core.handlemanager.domain.requests.vocabulary.specimen.ObjectType; import eu.dissco.core.handlemanager.exceptions.InvalidRequestException; @@ -358,28 +359,71 @@ void testCreateDigitalSpecimen() throws Exception { var responseReceived = service.createRecords(List.of(request)); // Then + then(pidRepository).should().postAttributesToDb(CREATED.getEpochSecond(), digitalSpecimen); assertThat(responseReceived).isEqualTo(responseExpected); } - @Test void testCreateDigitalSpecimenSpecimenExists() throws Exception { // Given byte[] handle = handles.get(0); - var request = genCreateRecordRequest(givenDigitalSpecimenRequestObjectNullOptionals(), + var digitalSpecimen = givenDigitalSpecimenRequestObjectNullOptionals(); + var request = genCreateRecordRequest(digitalSpecimen, RECORD_TYPE_DS); - List digitalSpecimen = genDigitalSpecimenAttributes(handle); + List digitalSpecimenAttributes = genDigitalSpecimenAttributes(handle); + var digitalSpecimenSublist = digitalSpecimenAttributes.stream() + .filter(row -> row.getType().equals(PRIMARY_SPECIMEN_OBJECT_ID.get())).toList(); + var responseExpected = givenRecordResponseWriteSmallResponse(digitalSpecimenSublist, + List.of(handle), + ObjectType.DIGITAL_SPECIMEN); given(pidNameGeneratorService.genHandleList(1)).willReturn(new ArrayList<>(List.of(handle))); - given(pidRepository.searchByNormalisedPhysicalIdentifier(anyList())).willReturn( - digitalSpecimen); + given(pidRepository.checkHandlesWritable(anyList())).willReturn(List.of(handle)); + given(profileProperties.getDomain()).willReturn(HANDLE_DOMAIN); + given(pidRepository.searchByNormalisedPhysicalIdentifier(anyList())).willReturn(List.of( + new HandleAttribute(FdoProfile.NORMALISED_SPECIMEN_OBJECT_ID, handle, + digitalSpecimen.getNormalisedPrimarySpecimenObjectId()))); + given(fdoRecordService.prepareUpdateAttributes(any(), eq(request.get("data").get("attributes")), + eq(ObjectType.DIGITAL_SPECIMEN))).willReturn(digitalSpecimenAttributes); + + // When + var result = service.createRecords(List.of(request)); + + // Then + then(pidRepository).should() + .updateRecordBatch(CREATED.getEpochSecond(), List.of(digitalSpecimenAttributes), true); + assertThat(result).isEqualTo(responseExpected); + } + + @Test + void testCreateDigitalSpecimenSpecimenExistsNotWritable() throws Exception { + // Given + byte[] handle = handles.get(0); + var digitalSpecimen = givenDigitalSpecimenRequestObjectNullOptionals(); + var request = genCreateRecordRequest(digitalSpecimen, + RECORD_TYPE_DS); + List digitalSpecimenAttributes = genDigitalSpecimenAttributes(handle); + var digitalSpecimenSublist = digitalSpecimenAttributes.stream() + .filter(row -> row.getType().equals(PRIMARY_SPECIMEN_OBJECT_ID.get())).toList(); + var responseExpected = givenRecordResponseWriteSmallResponse(digitalSpecimenSublist, + List.of(handle), + ObjectType.DIGITAL_SPECIMEN); + + given(pidNameGeneratorService.genHandleList(1)).willReturn(new ArrayList<>(List.of(handle))); + given(profileProperties.getDomain()).willReturn(HANDLE_DOMAIN); + given(pidRepository.searchByNormalisedPhysicalIdentifier(anyList())).willReturn(List.of( + new HandleAttribute(FdoProfile.NORMALISED_SPECIMEN_OBJECT_ID, handle, + digitalSpecimen.getNormalisedPrimarySpecimenObjectId()))); + given(fdoRecordService.prepareDigitalSpecimenRecordAttributes(digitalSpecimen, + handle)).willReturn(digitalSpecimenAttributes); // When - Exception e = assertThrows(InvalidRequestException.class, - () -> service.createRecords(List.of(request))); + var result = service.createRecords(List.of(request)); // Then - assertThat(e.getMessage()).contains(new String(handle, StandardCharsets.UTF_8)); + then(pidRepository).should() + .postAttributesToDb(CREATED.getEpochSecond(), digitalSpecimenAttributes); + assertThat(result).isEqualTo(responseExpected); } @Test @@ -424,6 +468,7 @@ void testCreateMasRecord() throws Exception { given(profileProperties.getDomain()).willReturn(HANDLE_DOMAIN); // When + var responseReceived = service.createRecords(List.of(request)); // Then From 7580c841ce34f273e54900e6d9281ddc9baf90e7 Mon Sep 17 00:00:00 2001 From: southeo Date: Tue, 12 Dec 2023 15:26:39 +0100 Subject: [PATCH 2/3] Vocab fixes --- .../requests/vocabulary/specimen/BaseTypeOfSpecimen.java | 4 ++-- .../requests/vocabulary/specimen/MaterialSampleType.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/BaseTypeOfSpecimen.java b/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/BaseTypeOfSpecimen.java index 8aa519d0..356d5e9b 100644 --- a/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/BaseTypeOfSpecimen.java +++ b/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/BaseTypeOfSpecimen.java @@ -4,12 +4,12 @@ public enum BaseTypeOfSpecimen { @JsonProperty("Material entity") MATERIAL("Material entity"), - @JsonProperty("Information artefact") INFO("informationArtefact"); + @JsonProperty("Information artefact") INFO("Information Artefact"); private final String state; - private BaseTypeOfSpecimen(String state) { + BaseTypeOfSpecimen(String state) { this.state = state; } diff --git a/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/MaterialSampleType.java b/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/MaterialSampleType.java index 6a0eb474..124e69ff 100644 --- a/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/MaterialSampleType.java +++ b/src/main/java/eu/dissco/core/handlemanager/domain/requests/vocabulary/specimen/MaterialSampleType.java @@ -7,12 +7,12 @@ public enum MaterialSampleType { @JsonProperty("Whole organism specimen") WHOLE_ORG("Whole organism specimen"), @JsonProperty("Organism part") ORG_PART("Organism part"), @JsonProperty("Organism product") ORG_PRODUCT("Organism product"), - @JsonProperty("Biome aggegation") AGGR_BIOME("Biome aggegation"), + @JsonProperty("Biome aggregation") AGGR_BIOME("Biome aggregation"), @JsonProperty("Bundle biome aggregation") BUNDLE_BIOME("Bundle biome aggregation"), @JsonProperty("Fossil") FOSSIL("Fossil"), @JsonProperty("Any biological specimen") ANY_BIO("Any biological specimen"), @JsonProperty("Aggregation") AGGR("Aggregation"), - @JsonProperty("Slurry biome aggegation") SLURRY_BIOME("Slurry biome aggegation"), + @JsonProperty("Slurry biome aggregation") SLURRY_BIOME("Slurry biome aggregation"), @JsonProperty("Other solid object") OTHER_SOLID("Other solid object"), @JsonProperty("Fluid in container") FLUID("Fluid in container"), @JsonProperty("Anthropogenic aggregation") ANTHRO_AGGR("Anthropogenic aggregation"), @@ -22,7 +22,7 @@ public enum MaterialSampleType { private final String state; - private MaterialSampleType(String state) { + MaterialSampleType(String state) { this.state = state; } From ac60b49406dfdf1286654cbd6510b60e33b32b7b Mon Sep 17 00:00:00 2001 From: southeo Date: Wed, 13 Dec 2023 12:52:33 +0100 Subject: [PATCH 3/3] Code review --- .../core/handlemanager/domain/FdoProfile.java | 2 +- .../repository/PidRepository.java | 15 +++++++-- .../handlemanager/service/PidService.java | 16 ++-------- .../repository/PidRepositoryIT.java | 18 +++++++++++ .../service/HandleServiceTest.java | 32 ------------------- 5 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/main/java/eu/dissco/core/handlemanager/domain/FdoProfile.java b/src/main/java/eu/dissco/core/handlemanager/domain/FdoProfile.java index 427d0fb6..259e4132 100644 --- a/src/main/java/eu/dissco/core/handlemanager/domain/FdoProfile.java +++ b/src/main/java/eu/dissco/core/handlemanager/domain/FdoProfile.java @@ -97,7 +97,7 @@ public enum FdoProfile { private final int index; - private FdoProfile(String attribute, int index) { + FdoProfile(String attribute, int index) { this.attribute = attribute; this.index = index; } diff --git a/src/main/java/eu/dissco/core/handlemanager/repository/PidRepository.java b/src/main/java/eu/dissco/core/handlemanager/repository/PidRepository.java index f4d3ff30..7a5a25f2 100644 --- a/src/main/java/eu/dissco/core/handlemanager/repository/PidRepository.java +++ b/src/main/java/eu/dissco/core/handlemanager/repository/PidRepository.java @@ -6,6 +6,7 @@ import static eu.dissco.core.handlemanager.domain.FdoProfile.PID_RECORD_ISSUE_NUMBER; import static eu.dissco.core.handlemanager.domain.FdoProfile.PID_STATUS; import static eu.dissco.core.handlemanager.domain.FdoProfile.PRIMARY_SPECIMEN_OBJECT_ID; +import static org.jooq.impl.DSL.select; import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute; import eu.dissco.core.handlemanager.exceptions.PidCreationException; @@ -73,8 +74,18 @@ public List resolveHandleAttributes(List handles) { public List searchByNormalisedPhysicalIdentifier( List normalisedPhysicalIdentifiers) { - - return searchByNormalisedPhysicalIdentifierQuery(normalisedPhysicalIdentifiers) + return context.select(HANDLES.IDX, HANDLES.HANDLE, HANDLES.TYPE, HANDLES.DATA) + .from(HANDLES) + .where(HANDLES.HANDLE.in(select(HANDLES.HANDLE).from(HANDLES) + .where(HANDLES.TYPE.eq(PID_STATUS.get().getBytes(StandardCharsets.UTF_8))) + .and(HANDLES.DATA.notEqual("ARCHIVED".getBytes(StandardCharsets.UTF_8))) + .and(HANDLES.HANDLE.in( + select(HANDLES.HANDLE).from(HANDLES) + .where(HANDLES.TYPE.eq(NORMALISED_SPECIMEN_OBJECT_ID.get().getBytes( + StandardCharsets.UTF_8))) + .and(HANDLES.DATA.in(normalisedPhysicalIdentifiers)) + )))) + .and(HANDLES.TYPE.eq(NORMALISED_SPECIMEN_OBJECT_ID.get().getBytes(StandardCharsets.UTF_8))) .fetch(this::mapToAttribute); } diff --git a/src/main/java/eu/dissco/core/handlemanager/service/PidService.java b/src/main/java/eu/dissco/core/handlemanager/service/PidService.java index a1b2abc6..dc4632d0 100644 --- a/src/main/java/eu/dissco/core/handlemanager/service/PidService.java +++ b/src/main/java/eu/dissco/core/handlemanager/service/PidService.java @@ -344,13 +344,9 @@ private ProcessedDigitalSpecimenRequest processSpecimenRequests( var registeredPhysicalIdentiferMap = registeredPhysicalIdentifiers.stream() .collect(Collectors.toMap(row -> new String(row.getData(), StandardCharsets.UTF_8), row -> new String(row.getHandle(), StandardCharsets.UTF_8))); - var writableHandles = pidRepository.checkHandlesWritable( - registeredPhysicalIdentiferMap.values().stream().map(s -> s.getBytes( - StandardCharsets.UTF_8)).toList()).stream() - .map(h -> new String(h, StandardCharsets.UTF_8)).collect(Collectors.toSet()); var updates = specimenRequests.stream() - .filter(request -> requestExistsAndIsWriteable(request, registeredPhysicalIdentiferMap, - writableHandles)) + .filter(request -> registeredPhysicalIdentiferMap.containsKey( + request.getNormalisedPrimarySpecimenObjectId())) .map(request -> new DigitalSpecimenUpdateWrapper( registeredPhysicalIdentiferMap.get(request.getNormalisedPrimarySpecimenObjectId()), request @@ -366,14 +362,6 @@ private ProcessedDigitalSpecimenRequest processSpecimenRequests( return new ProcessedDigitalSpecimenRequest(specimenRequests, updates); } - private boolean requestExistsAndIsWriteable(DigitalSpecimenRequest request, - Map registeredPhysicalIdentifiers, Set writableHandles) { - return registeredPhysicalIdentifiers.containsKey(request.getNormalisedPrimarySpecimenObjectId()) - && - writableHandles.contains( - registeredPhysicalIdentifiers.get(request.getNormalisedPrimarySpecimenObjectId())); - } - protected List createMediaObject(List requestAttributes, Iterator handleIterator) throws InvalidRequestException, JsonProcessingException, PidResolutionException { diff --git a/src/test/java/eu/dissco/core/handlemanager/repository/PidRepositoryIT.java b/src/test/java/eu/dissco/core/handlemanager/repository/PidRepositoryIT.java index c2476971..e1d00c47 100644 --- a/src/test/java/eu/dissco/core/handlemanager/repository/PidRepositoryIT.java +++ b/src/test/java/eu/dissco/core/handlemanager/repository/PidRepositoryIT.java @@ -322,6 +322,24 @@ void testSearchByPhysicalSpecimenId() throws Exception { assertThat(response).isEqualTo(expected); } + @Test + void testSearchByPhysicalSpecimenIdIsArchived() { + //Given + var handle = HANDLE.getBytes(StandardCharsets.UTF_8); + var record = List.of(new HandleAttribute(NORMALISED_SPECIMEN_OBJECT_ID, handle, + NORMALISED_PRIMARY_SPECIMEN_OBJECT_ID_TESTVAL), + new HandleAttribute(PID_STATUS, handle, "ARCHIVED")); + + postAttributes(record); + + // When + var response = pidRepository.searchByNormalisedPhysicalIdentifier( + List.of(NORMALISED_PRIMARY_SPECIMEN_OBJECT_ID_TESTVAL.getBytes(StandardCharsets.UTF_8))); + + // Then + assertThat(response).isEmpty(); + } + @Test void testUpdateRecord() throws Exception { // Given diff --git a/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java b/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java index f967a676..e7f88108 100644 --- a/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java +++ b/src/test/java/eu/dissco/core/handlemanager/service/HandleServiceTest.java @@ -378,7 +378,6 @@ void testCreateDigitalSpecimenSpecimenExists() throws Exception { ObjectType.DIGITAL_SPECIMEN); given(pidNameGeneratorService.genHandleList(1)).willReturn(new ArrayList<>(List.of(handle))); - given(pidRepository.checkHandlesWritable(anyList())).willReturn(List.of(handle)); given(profileProperties.getDomain()).willReturn(HANDLE_DOMAIN); given(pidRepository.searchByNormalisedPhysicalIdentifier(anyList())).willReturn(List.of( new HandleAttribute(FdoProfile.NORMALISED_SPECIMEN_OBJECT_ID, handle, @@ -395,37 +394,6 @@ void testCreateDigitalSpecimenSpecimenExists() throws Exception { assertThat(result).isEqualTo(responseExpected); } - @Test - void testCreateDigitalSpecimenSpecimenExistsNotWritable() throws Exception { - // Given - byte[] handle = handles.get(0); - var digitalSpecimen = givenDigitalSpecimenRequestObjectNullOptionals(); - var request = genCreateRecordRequest(digitalSpecimen, - RECORD_TYPE_DS); - List digitalSpecimenAttributes = genDigitalSpecimenAttributes(handle); - var digitalSpecimenSublist = digitalSpecimenAttributes.stream() - .filter(row -> row.getType().equals(PRIMARY_SPECIMEN_OBJECT_ID.get())).toList(); - var responseExpected = givenRecordResponseWriteSmallResponse(digitalSpecimenSublist, - List.of(handle), - ObjectType.DIGITAL_SPECIMEN); - - given(pidNameGeneratorService.genHandleList(1)).willReturn(new ArrayList<>(List.of(handle))); - given(profileProperties.getDomain()).willReturn(HANDLE_DOMAIN); - given(pidRepository.searchByNormalisedPhysicalIdentifier(anyList())).willReturn(List.of( - new HandleAttribute(FdoProfile.NORMALISED_SPECIMEN_OBJECT_ID, handle, - digitalSpecimen.getNormalisedPrimarySpecimenObjectId()))); - given(fdoRecordService.prepareDigitalSpecimenRecordAttributes(digitalSpecimen, - handle)).willReturn(digitalSpecimenAttributes); - - // When - var result = service.createRecords(List.of(request)); - - // Then - then(pidRepository).should() - .postAttributesToDb(CREATED.getEpochSecond(), digitalSpecimenAttributes); - assertThat(result).isEqualTo(responseExpected); - } - @Test void testCreateMediaObjectRecord() throws Exception { // Given