Skip to content

Commit

Permalink
MODLD-654: Retain Resource properties that are not rendered in the UI (
Browse files Browse the repository at this point in the history
  • Loading branch information
askhat-abishev authored Feb 12, 2025
1 parent a05daa6 commit c9ad92a
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package org.folio.linked.data.service.resource;

import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE;
import static org.folio.linked.data.util.ResourceUtils.getPrimaryMainTitles;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
Expand All @@ -16,15 +14,14 @@
import org.folio.linked.data.domain.dto.WorkField;
import org.folio.linked.data.exception.RequestProcessingExceptionBuilder;
import org.folio.linked.data.mapper.dto.ResourceDtoMapper;
import org.folio.linked.data.model.entity.RawMarc;
import org.folio.linked.data.model.entity.Resource;
import org.folio.linked.data.model.entity.event.ResourceCreatedEvent;
import org.folio.linked.data.model.entity.event.ResourceDeletedEvent;
import org.folio.linked.data.model.entity.event.ResourceReplacedEvent;
import org.folio.linked.data.model.entity.event.ResourceUpdatedEvent;
import org.folio.linked.data.repo.FolioMetadataRepository;
import org.folio.linked.data.repo.ResourceRepository;
import org.folio.linked.data.service.resource.edge.ResourceEdgeService;
import org.folio.linked.data.service.resource.copy.ResourceCopyService;
import org.folio.linked.data.service.resource.graph.ResourceGraphService;
import org.folio.linked.data.service.resource.meta.MetadataService;
import org.folio.spring.FolioExecutionContext;
Expand All @@ -46,8 +43,8 @@ public class ResourceServiceImpl implements ResourceService {
private final FolioMetadataRepository folioMetadataRepo;
private final RequestProcessingExceptionBuilder exceptionBuilder;
private final ApplicationEventPublisher applicationEventPublisher;
private final ResourceEdgeService resourceEdgeService;
private final FolioExecutionContext folioExecutionContext;
private final ResourceCopyService resourceCopyService;

@Override
public ResourceResponseDto createResource(ResourceRequestDto resourceDto) {
Expand Down Expand Up @@ -113,9 +110,8 @@ private Resource getResource(Long id) {

private Resource saveNewResource(ResourceRequestDto resourceDto, Resource old) {
var mapped = resourceDtoMapper.toEntity(resourceDto);
resourceEdgeService.copyOutgoingEdges(old, mapped);
resourceCopyService.copyEdgesAndProperties(old, mapped);
metadataService.ensure(mapped, old.getFolioMetadata());
copyUnmappedMarc(old, mapped);
mapped.setCreatedDate(old.getCreatedDate());
mapped.setVersion(old.getVersion() + 1);
mapped.setCreatedBy(old.getCreatedBy());
Expand All @@ -136,14 +132,4 @@ private String toLogString(ResourceRequestDto resourceDto) {
return String.format("Type: %s, Title: %s", type, titles);
}

private void copyUnmappedMarc(Resource old, Resource mapped) {
if (mapped.isOfType(INSTANCE)) {
Optional.ofNullable(old.getUnmappedMarc())
.ifPresent(unmappedMarc -> {
var newUnmappedMarc = new RawMarc(mapped).setContent(unmappedMarc.getContent());
mapped.setUnmappedMarc(newUnmappedMarc);
});
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.folio.linked.data.service.resource.copy;

import org.folio.linked.data.model.entity.Resource;

public interface ResourceCopyService {

void copyEdgesAndProperties(Resource old, Resource updated);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.folio.linked.data.service.resource.copy;

import static java.util.Collections.emptySet;
import static org.folio.ld.dictionary.PropertyDictionary.CITATION_COVERAGE;
import static org.folio.ld.dictionary.PropertyDictionary.CREDITS_NOTE;
import static org.folio.ld.dictionary.PropertyDictionary.DATES_OF_PUBLICATION_NOTE;
import static org.folio.ld.dictionary.PropertyDictionary.GEOGRAPHIC_COVERAGE;
import static org.folio.ld.dictionary.PropertyDictionary.GOVERNING_ACCESS_NOTE;
import static org.folio.ld.dictionary.PropertyDictionary.LOCATION_OF_ORIGINALS_DUPLICATES;
import static org.folio.ld.dictionary.PropertyDictionary.OTHER_EVENT_INFORMATION;
import static org.folio.ld.dictionary.PropertyDictionary.PARTICIPANT_NOTE;
import static org.folio.ld.dictionary.PropertyDictionary.PUBLICATION_FREQUENCY;
import static org.folio.ld.dictionary.PropertyDictionary.REFERENCES;
import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE;
import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK;

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 java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.folio.linked.data.model.entity.RawMarc;
import org.folio.linked.data.model.entity.Resource;
import org.folio.linked.data.service.resource.edge.ResourceEdgeService;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class ResourceCopyServiceImpl implements ResourceCopyService {

private static final Map<String, Set<String>> PROPERTIES_TO_BE_COPIED = Map.of(
INSTANCE.getUri(), Set.of(
PUBLICATION_FREQUENCY.getValue(),
DATES_OF_PUBLICATION_NOTE.getValue(),
GOVERNING_ACCESS_NOTE.getValue(),
CREDITS_NOTE.getValue(),
PARTICIPANT_NOTE.getValue(),
CITATION_COVERAGE.getValue(),
LOCATION_OF_ORIGINALS_DUPLICATES.getValue()
),
WORK.getUri(), Set.of(
REFERENCES.getValue(),
OTHER_EVENT_INFORMATION.getValue(),
GEOGRAPHIC_COVERAGE.getValue()
)
);

private final ResourceEdgeService resourceEdgeService;
private final ObjectMapper objectMapper;

@Override
public void copyEdgesAndProperties(Resource old, Resource updated) {
resourceEdgeService.copyOutgoingEdges(old, updated);
copyUnmappedMarc(old, updated);
copyProperties(old, updated);
}

private void copyUnmappedMarc(Resource from, Resource to) {
if (to.isOfType(INSTANCE)) {
Optional.ofNullable(from.getUnmappedMarc())
.ifPresent(unmappedMarc -> {
var newUnmappedMarc = new RawMarc(to).setContent(unmappedMarc.getContent());
to.setUnmappedMarc(newUnmappedMarc);
});
}
}

@SneakyThrows
private void copyProperties(Resource from, Resource to) {
if (from.getDoc() == null) {
return;
}
var properties = getProperties(from);
if (!properties.isEmpty()) {
var toDoc = to.getDoc() == null
? new HashMap<String, List<String>>()
: objectMapper.treeToValue(to.getDoc(), new TypeReference<HashMap<String, List<String>>>() {});
properties.forEach(entry -> toDoc.put(entry.getKey(), entry.getValue()));
to.setDoc(objectMapper.convertValue(toDoc, JsonNode.class));
}
}

private List<Map.Entry<String, List<String>>> getProperties(Resource from) throws JsonProcessingException {
var fromDoc = objectMapper.treeToValue(from.getDoc(), new TypeReference<HashMap<String, List<String>>>() {});
var fromType = from.getTypes()
.stream()
.findFirst()
.orElseThrow()
.getUri();
var propertiesToCopy = PROPERTIES_TO_BE_COPIED.getOrDefault(fromType, emptySet());
return fromDoc.entrySet()
.stream()
.filter(entry -> propertiesToCopy.contains(entry.getKey()))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import static org.folio.linked.data.test.TestUtil.emptyRequestProcessingException;
import static org.folio.linked.data.test.TestUtil.random;
import static org.folio.linked.data.test.TestUtil.randomLong;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
Expand All @@ -33,7 +31,6 @@
import org.folio.linked.data.exception.RequestProcessingException;
import org.folio.linked.data.exception.RequestProcessingExceptionBuilder;
import org.folio.linked.data.mapper.dto.ResourceDtoMapper;
import org.folio.linked.data.model.entity.RawMarc;
import org.folio.linked.data.model.entity.Resource;
import org.folio.linked.data.model.entity.ResourceEdge;
import org.folio.linked.data.model.entity.event.ResourceCreatedEvent;
Expand All @@ -42,7 +39,7 @@
import org.folio.linked.data.model.entity.event.ResourceUpdatedEvent;
import org.folio.linked.data.repo.FolioMetadataRepository;
import org.folio.linked.data.repo.ResourceRepository;
import org.folio.linked.data.service.resource.edge.ResourceEdgeService;
import org.folio.linked.data.service.resource.copy.ResourceCopyService;
import org.folio.linked.data.service.resource.graph.ResourceGraphService;
import org.folio.linked.data.service.resource.meta.MetadataService;
import org.folio.spring.FolioExecutionContext;
Expand Down Expand Up @@ -77,9 +74,9 @@ class ResourceServiceImplTest {
@Mock
private RequestProcessingExceptionBuilder exceptionBuilder;
@Mock
private ResourceEdgeService resourceEdgeService;
@Mock
private FolioExecutionContext folioExecutionContext;
@Mock
private ResourceCopyService resourceCopyService;

@Test
void create_shouldPersistMappedResourceAndNotPublishResourceCreatedEvent_forResourceWithNoWork() {
Expand Down Expand Up @@ -235,6 +232,7 @@ void update_shouldSaveUpdatedResourceAndSendResourceUpdatedEvent_forResourceWith
verify(resourceGraphService).saveMergingGraph(work);
verify(folioExecutionContext).getUserId();
verify(applicationEventPublisher).publishEvent(new ResourceUpdatedEvent(work));
verify(resourceCopyService).copyEdgesAndProperties(oldWork, work);
}

@Test
Expand Down Expand Up @@ -263,30 +261,7 @@ void update_shouldSaveUpdatedResourceAndSendReplaceEvent_forResourceWithDifferen
verify(resourceGraphService).breakEdgesAndDelete(oldInstance);
verify(resourceGraphService).saveMergingGraph(mapped);
verify(applicationEventPublisher).publishEvent(new ResourceReplacedEvent(oldInstance, mapped.getId()));
}

@Test
void update_shouldRetainUnmappedMarc() {
// given
var oldId = randomLong();
var oldInstance = new Resource()
.setId(oldId)
.addTypes(INSTANCE);
var rawMarc = "raw marc";
var unmappedMarc = new RawMarc(oldInstance).setContent(rawMarc);
oldInstance.setUnmappedMarc(unmappedMarc);
when(resourceRepo.findById(oldId)).thenReturn(Optional.of(oldInstance));
var mapped = new Resource().addTypes(INSTANCE);
var instanceDto = new ResourceRequestDto();
when(resourceDtoMapper.toEntity(instanceDto)).thenReturn(mapped);
when(resourceGraphService.saveMergingGraph(mapped)).thenReturn(new Resource());

// when
resourceService.updateResource(oldId, instanceDto);

// then
assertNotNull(mapped.getUnmappedMarc());
assertEquals(rawMarc, mapped.getUnmappedMarc().getContent());
verify(resourceCopyService).copyEdgesAndProperties(oldInstance, mapped);
}

@Test
Expand Down
Loading

0 comments on commit c9ad92a

Please sign in to comment.