From 702eac1e9d25477d2171105ea2ae4fd895b0803a Mon Sep 17 00:00:00 2001 From: Homada Boumedane <homada.boumedane@unige.ch> Date: Mon, 17 Feb 2025 15:34:50 +0100 Subject: [PATCH 1/3] refactor: dissemination package use a checksum on the list of subsetItems to discriminate and reuse them if we ask for the same dip. Closes: DLCM-2830 --- .../java/ch/dlcm/business/OrderService.java | 53 ++++++++- .../controller/access/SearchController.java | 108 ++++++++++++------ .../DisseminationInfoPackageRepository.java | 3 + .../ch/dlcm/repository/OrderRepository.java | 14 +++ .../dissemination/BasicDipBuilderService.java | 14 ++- .../dissemination/DipBuilderService.java | 20 +++- .../DisseminationPolicyProvider.java | 3 + .../HederaDipBuilderService.java | 7 +- .../dissemination/IiifDipBuilderService.java | 7 +- .../dissemination/OaisDipBuilderService.java | 7 +- .../main/java/ch/dlcm/model/access/Order.java | 12 ++ .../main/resources/scripts/upgrade22to30.sql | 6 +- 12 files changed, 207 insertions(+), 47 deletions(-) diff --git a/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java b/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java index 16702c5150..101887cc48 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java @@ -26,9 +26,14 @@ package ch.dlcm.business; import static ch.dlcm.model.access.Order.OrderStatus.SUBMITTED; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.xml.transform.TransformerFactoryConfigurationError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,9 +50,11 @@ import org.springframework.validation.FieldError; import jakarta.transaction.Transactional; +import ch.unige.solidify.ChecksumAlgorithm; import ch.unige.solidify.SolidifyConstants; import ch.unige.solidify.config.SolidifyEventPublisher; import ch.unige.solidify.exception.SolidifyFileDeleteException; +import ch.unige.solidify.exception.SolidifyProcessingException; import ch.unige.solidify.exception.SolidifyRuntimeException; import ch.unige.solidify.rest.ActionName; import ch.unige.solidify.rest.RestCollection; @@ -55,6 +62,7 @@ import ch.unige.solidify.rest.RestCollectionPage; import ch.unige.solidify.rest.Result; import ch.unige.solidify.service.ResourceService; import ch.unige.solidify.util.FileTool; +import ch.unige.solidify.util.HashTool; import ch.unige.solidify.util.StringTool; import ch.dlcm.config.DLCMProperties; @@ -84,6 +92,7 @@ public class OrderService extends ResourceService<Order> { private final DataSize fileSizeLimit; private final String orderLocation; private final SearchMgmt searchMgmt; + private final ChecksumAlgorithm defaultChecksumAlgorithm; private final ArchivalInfoPackageService aipService; private final OrderSubsetItemRepository orderSubsetItemRepository; private final TrustedDisseminationPolicyRemoteResourceService disseminationPolicyRemoteResourceService; @@ -99,6 +108,7 @@ public class OrderService extends ResourceService<Order> { this.disseminationPolicyRemoteResourceService = disseminationPolicyRemoteResourceService; this.fileSizeLimit = dlcmProperties.getParameters().getFileSizeLimit(); this.orderLocation = dlcmProperties.getOrderLocation(); + this.defaultChecksumAlgorithm = ChecksumAlgorithm.valueOf(dlcmProperties.getParameters().getDefaultChecksum()); } public Order saveOrder(Order order) { @@ -179,19 +189,27 @@ public class OrderService extends ResourceService<Order> { public Order createOrderForAIP(String aipId, DisseminationPolicyDto disseminationPolicy) { final Order order = new Order(); + List<OrderSubsetItem> subsetItemList = disseminationPolicy.getSubsetItemList(); order.setName(aipId); order.setQueryType(QueryType.DIRECT); order.setQuery(aipId); order.setDisseminationPolicyId(disseminationPolicy.getDisseminationPolicyId()); order.setOrganizationalUnitDisseminationPolicyId(disseminationPolicy.getOrganizationalUnitDisseminationPolicyId()); + this.calculateChecksum(order, subsetItemList); //calculate and set checksum final Order savedOrder = this.save(order); - List<OrderSubsetItem> subsetItemList = disseminationPolicy.getSubsetItemList(); + + if (subsetItemList == null) { // if no subsetItemList is provided, set it to an empty list + subsetItemList = List.of(); + } + subsetItemList.forEach(subsetItem -> { subsetItem.setOrder(savedOrder); subsetItem.setCreatedBy(savedOrder.getCreatedBy()); subsetItem.setUpdatedBy(savedOrder.getUpdatedBy()); }); + this.orderSubsetItemRepository.saveAll(subsetItemList); + return savedOrder; } @@ -212,10 +230,15 @@ public class OrderService extends ResourceService<Order> { this.submitOrder(order1); } - public List<Order> findFullDirectOrderByAipAndDisseminationPolicy(String aipId, String disseminationPolicyId) { + public List<Order> findDirectOrderByAipAndDisseminationPolicy(String aipId, String disseminationPolicyId) { return ((OrderRepository) this.itemRepository).findFullDirectOrderByAipAndDisseminationPolicyId(aipId, disseminationPolicyId); } + public List<Order> findDirectOrderByDisseminationPolicyAndSubsetChecksum(String aipId, String disseminationPolicyId, String checksum) { + return ((OrderRepository) this.itemRepository).findDirectOrderByDisseminationPolicyIdAndAipIdAndChecksum(aipId, disseminationPolicyId, + checksum); + } + public List<Order> findByAip(String aipId) { return ((OrderRepository) this.itemRepository).findByAip(aipId); } @@ -298,6 +321,32 @@ public class OrderService extends ResourceService<Order> { return ((OrderRepository) this.itemRepository).getSize(resId); } + public Optional<Order> isThereAnyOrderWithSameChecksum(Order order) { + return ((OrderRepository) this.itemRepository).findOrdersByChecksum(order.getChecksum(), order.getResId()) + .stream() + .findFirst(); + } + + private void calculateChecksum(Order order, List<OrderSubsetItem> subsetItems) { + if (subsetItems != null && !subsetItems.isEmpty()) { + // Create a string combining all paths, sorted by path to ensure consistent checksum + String content = subsetItems.stream() + .map(OrderSubsetItem::getItemPath) + .sorted() + .collect(Collectors.joining("|")); + if (content.isEmpty()) { + order.setChecksum(null); + return; + } + try { + String hash = HashTool.hash(this.defaultChecksumAlgorithm.toString(), content.getBytes(StandardCharsets.UTF_8)); + order.setChecksum(hash); + } catch (TransformerFactoryConfigurationError | NoSuchAlgorithmException e) { + throw new SolidifyProcessingException(e.getMessage(), e); + } + } + } + @Override public OrderSpecification getSpecification(Order resource) { return new OrderSpecification(resource); diff --git a/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java b/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java index f1a8ba0e72..5afdcaf598 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java +++ b/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java @@ -23,13 +23,18 @@ package ch.dlcm.controller.access; +import static ch.dlcm.DLCMConstants.DISSEMINATION_POLICY_BASIC_ID; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +import java.util.stream.Collectors; +import javax.xml.transform.TransformerFactoryConfigurationError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,10 +55,12 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import ch.unige.solidify.ChecksumAlgorithm; import ch.unige.solidify.SolidifyConstants; import ch.unige.solidify.auth.model.AuthApplicationRole; import ch.unige.solidify.auth.service.ApplicationRoleListService; import ch.unige.solidify.config.SolidifyEventPublisher; +import ch.unige.solidify.exception.SolidifyProcessingException; import ch.unige.solidify.exception.SolidifyRestException; import ch.unige.solidify.exception.SolidifyRuntimeException; import ch.unige.solidify.model.dto.CitationDto; @@ -65,6 +72,7 @@ import ch.unige.solidify.security.EveryonePermissions; import ch.unige.solidify.service.DownloadTokenService; import ch.unige.solidify.service.rest.abstractservice.IndexMetadataRemoteResourceService; import ch.unige.solidify.util.FileTool; +import ch.unige.solidify.util.HashTool; import ch.unige.solidify.util.StringTool; import ch.dlcm.DLCMConstants; @@ -76,6 +84,7 @@ import ch.dlcm.message.ArchiveStatisticMessage.StatisticType; import ch.dlcm.model.MetadataVisibility; import ch.dlcm.model.access.Order; import ch.dlcm.model.access.Order.OrderStatus; +import ch.dlcm.model.access.OrderSubsetItem; import ch.dlcm.model.dto.DisseminationPolicyDto; import ch.dlcm.model.index.ArchiveMetadata; import ch.dlcm.model.oais.DisseminationInfoPackage; @@ -100,6 +109,7 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro private final DownloadTokenService downloadTokenService; private final TrustedUserRemoteResourceService trustedUserRemoteResourceService; private final DisseminationPolicyProvider disseminationPolicyProvider; + private final ChecksumAlgorithm defaultChecksumAlgorithm; protected SearchController( IndexMetadataRemoteResourceService<ArchiveMetadata> indexResourceRemoteService, @@ -119,6 +129,7 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro this.downloadTokenService = downloadTokenService; this.trustedUserRemoteResourceService = trustedUserRemoteResourceService; this.disseminationPolicyProvider = disseminationPolicyProvider; + this.defaultChecksumAlgorithm = ChecksumAlgorithm.valueOf(dlcmProperties.getParameters().getDefaultChecksum()); } @Override @@ -165,8 +176,8 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro DisseminationPolicy disseminationPolicy; if (orderId == null) { //If order is not specified, check a direct order with the aipId as dipName and disseminationPolicyPublic and not itemList selected. - List<Order> orderList = this.orderService.findFullDirectOrderByAipAndDisseminationPolicy(dipName, - DLCMConstants.DISSEMINATION_POLICY_BASIC_ID); + List<Order> orderList = this.orderService.findDirectOrderByAipAndDisseminationPolicy(dipName, + DISSEMINATION_POLICY_BASIC_ID); if (orderList.isEmpty()) { throw new IllegalStateException("Order for DIP " + dipName + " is missing"); } @@ -221,61 +232,77 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro + "|| @downloadWithAclPermissionService.isAllowed(#aipId)") public HttpEntity<String> prepareDownload(@PathVariable String aipId, @RequestBody(required = false) DisseminationPolicyDto disseminationPolicyDto) { + if (disseminationPolicyDto == null) { disseminationPolicyDto = new DisseminationPolicyDto(); } + if (disseminationPolicyDto.getDisseminationPolicyId() == null) { - disseminationPolicyDto.setDisseminationPolicyId(DLCMConstants.DISSEMINATION_POLICY_BASIC_ID); + disseminationPolicyDto.setDisseminationPolicyId(DISSEMINATION_POLICY_BASIC_ID); } - List<DisseminationInfoPackage> dipList = List.of(); - if (disseminationPolicyDto.getSubsetItemList() == null) { + + List<DisseminationInfoPackage> dipList; + boolean isBasicPolicy = disseminationPolicyDto.getDisseminationPolicyId().equals(DISSEMINATION_POLICY_BASIC_ID); + if (isBasicPolicy && disseminationPolicyDto.getSubsetItemList() != null) { + // Basic policy with subset items - find specific DIP + String hash = this.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); + dipList = this.dipRepository.findByDisseminationPolicyIdAndAipIdAndSubsetItems(disseminationPolicyDto.getDisseminationPolicyId(), aipId, + hash); + } else { + // Non-basic policy - find DIP by policy and AIP dipList = this.dipRepository.findByFullDisseminationPolicyIdAndAipId(disseminationPolicyDto.getDisseminationPolicyId(), aipId); - disseminationPolicyDto.setSubsetItemList(List.of()); } + List<Order> directOrders; if (dipList.size() > 1) { log.error("AIP download: too many DIPs"); return new ResponseEntity<>("Too many DIPs found", HttpStatus.INTERNAL_SERVER_ERROR); - } else if (dipList.isEmpty()) { - /* - * DIP does not exist yet -> create a DIRECT order for the AIP that will create a DIP with only one - * AIP inside - */ - - // Create order to download AIP and create DIP - List<Order> orderList = List.of(); - if (disseminationPolicyDto.getSubsetItemList().isEmpty()) { - orderList = this.orderService.findFullDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); + } + + if (dipList.isEmpty()) { // No DIP found + // Check if the DTO has asked for subset items + if (disseminationPolicyDto.getSubsetItemList() != null) { + // calculate checksum of subset items + String hash = this.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); + directOrders = isBasicPolicy + ? + orderService.findDirectOrderByDisseminationPolicyAndSubsetChecksum(aipId, disseminationPolicyDto.getDisseminationPolicyId(), + hash) + : + orderService.findDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); + } else { + directOrders = this.orderService.findDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); } - final Order order; - if (orderList.isEmpty()) { - order = this.orderService.createOrderForAIP(aipId, disseminationPolicyDto); + + if (directOrders.isEmpty()) { + // create a new order + Order order = this.orderService.createOrderForAIP(aipId, disseminationPolicyDto); this.orderService.submitOrder(order); - } else if (orderList.size() == 1) { - order = orderList.get(0); - if (order.getStatus() == OrderStatus.IN_PROGRESS) { - this.orderService.submitOrder(order); - } else if (order.getStatus() == OrderStatus.IN_ERROR) { - log.error("AIP download: order in error"); - return new ResponseEntity<>("Order is in error", HttpStatus.INTERNAL_SERVER_ERROR); + return new ResponseEntity<>(order.getResId(), HttpStatus.ACCEPTED); + } else if (directOrders.size() == 1) { + Order order = directOrders.get(0); + switch (order.getStatus()) { + case IN_PROGRESS: + orderService.submitOrder(order); + break; + case IN_ERROR: + log.error("AIP download: order in error"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Order is in error"); + default: + // do nothing } } else { log.error("AIP download: too many orders"); return new ResponseEntity<>("Too many orders found", HttpStatus.INTERNAL_SERVER_ERROR); } - return new ResponseEntity<>(order.getResId(), HttpStatus.ACCEPTED); - - } else { - /* - * DIP already exists - */ - final DisseminationInfoPackage dip = dipList.get(0); + } + log.debug("DIP already exists"); + final DisseminationInfoPackage dip = dipList.get(0); if (dip.getOrders().size() != 1) { return new ResponseEntity<>("Exactly one order should be associated to the DIP " + dip.getResId(), HttpStatus.INTERNAL_SERVER_ERROR); } return new ResponseEntity<>(dip.getOrders().get(0).getResId(), HttpStatus.ACCEPTED); - } } @Override @@ -371,4 +398,17 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro final ArchiveMetadata archive = this.getIndexResourceRemoteService().getIndexMetadata(dipName); return this.disseminationPolicyProvider.calculateFinalFileName(disseminationPolicy, archive.getTitle(), dipName); } + + private String calculateChecksum(List<OrderSubsetItem> subsetItems) { + // Create a string combining all paths, sorted by path to ensure consistent checksum + String content = subsetItems.stream() + .map(OrderSubsetItem::getItemPath) + .sorted() + .collect(Collectors.joining("|")); + try { + return HashTool.hash(this.defaultChecksumAlgorithm.toString(), content.getBytes(StandardCharsets.UTF_8)); + } catch (TransformerFactoryConfigurationError | NoSuchAlgorithmException e) { + throw new SolidifyProcessingException(e.getMessage(), e); + } + } } diff --git a/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java b/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java index 1ff12dd331..596ba28aba 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java +++ b/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java @@ -76,4 +76,7 @@ public interface DisseminationInfoPackageRepository extends SolidifyRepository<D + "AND si IS NULL " + "AND order.queryType = 'DIRECT'") List<DisseminationInfoPackage> findByFullDisseminationPolicyIdAndAipId(String disseminationPolicyId, String aipId); + + @Query("SELECT dip FROM DisseminationInfoPackage dip JOIN dip.orders order JOIN dip.aips aip WHERE aip.resId = :aipId AND order.disseminationPolicyId = :disseminationPolicyId AND order.checksum = :checksum") + List<DisseminationInfoPackage> findByDisseminationPolicyIdAndAipIdAndSubsetItems(String disseminationPolicyId, String aipId, String checksum); } diff --git a/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java b/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java index 09771e5e8a..b23b1e2e90 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java +++ b/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java @@ -54,8 +54,22 @@ public interface OrderRepository extends SolidifyRepository<Order> { @Query("SELECT DISTINCT o FROM Order o JOIN o.aipPackages aip LEFT JOIN o.subsetItems si WHERE aip.resId=:aipId and o.queryType = 'DIRECT' and o.disseminationPolicyId=:disseminationPolicyId and si IS NULL") List<Order> findFullDirectOrderByAipAndDisseminationPolicyId(String aipId, String disseminationPolicyId); + @Query("SELECT DISTINCT o FROM Order o JOIN o.aipPackages aip WHERE aip.resId=:aipId and o.queryType = 'DIRECT' and o.disseminationPolicyId=:disseminationPolicyId and o.checksum =:checksum") + List<Order> findDirectOrderByDisseminationPolicyIdAndAipIdAndChecksum(String aipId, String disseminationPolicyId, String checksum); + List<Order> findByStatusIn(List<OrderStatus> statuses); @Query("SELECT COALESCE(SUM(df.fileSize), 0) FROM Order o JOIN o.aipPackages aip JOIN aip.dataFiles df WHERE o.resId = :orderId") long getSize(String orderId); + + /** + * Find orders that have the same checksum + * + * @param checksum the checksum to search for + * @param orderId the order ID to exclude from search + * @return list of orders with matching checksums + */ + @Query("SELECT o FROM Order o WHERE o.checksum = :checksum AND o.resId != :orderId ORDER BY o.creation.when DESC") + List<Order> findOrdersByChecksum(String checksum, String orderId); + } diff --git a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/BasicDipBuilderService.java b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/BasicDipBuilderService.java index 6c38ce505e..1868ebce6b 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/BasicDipBuilderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/BasicDipBuilderService.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.stereotype.Service; import ch.unige.solidify.exception.SolidifyRuntimeException; @@ -37,22 +38,31 @@ import ch.unige.solidify.service.MessageService; import ch.unige.solidify.util.FileTool; import ch.dlcm.DLCMConstants; +import ch.dlcm.business.OrderService; import ch.dlcm.config.DLCMProperties; import ch.dlcm.config.DLCMRepositoryDescription; +import ch.dlcm.controller.AccessController; import ch.dlcm.model.access.Order; import ch.dlcm.model.oais.ArchivalInfoPackage; import ch.dlcm.service.MetadataService; @Service +@ConditionalOnBean(AccessController.class) public class BasicDipBuilderService extends DipBuilderService { - public BasicDipBuilderService(DLCMProperties dlcmProperties, MessageService messageService, MetadataService metadataService, + public BasicDipBuilderService(DLCMProperties dlcmProperties, + MessageService messageService, + MetadataService metadataService, + OrderService orderService, DLCMRepositoryDescription repository) { - super(dlcmProperties, messageService, metadataService, repository); + super(dlcmProperties, messageService, metadataService, orderService, repository); } @Override public void buildDisseminationPolicyDip(Path workingFolder, ArchivalInfoPackage aip, Order order) { + if (this.orderService.isThereAnyOrderWithSameChecksum(order).isPresent()) { + return; // Do not build DIP if there is already an order with the same checksum + } // Extract datacite part from dlcm.xml to a new file and delete it this.extractDataciteMetadata(workingFolder, aip.getMetadataVersion()); this.deleteUpdatedMetadataFiles(workingFolder); diff --git a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DipBuilderService.java b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DipBuilderService.java index 94cf9494fc..8c38a64ea5 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DipBuilderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DipBuilderService.java @@ -51,6 +51,7 @@ import ch.unige.solidify.util.ZipTool; import ch.dlcm.DLCMConstants; import ch.dlcm.DLCMMetadataVersion; +import ch.dlcm.business.OrderService; import ch.dlcm.config.DLCMProperties; import ch.dlcm.config.DLCMRepositoryDescription; import ch.dlcm.model.Access; @@ -66,13 +67,16 @@ public abstract class DipBuilderService extends DLCMService { private static final Logger log = LoggerFactory.getLogger(DipBuilderService.class); protected final MetadataService metadataService; + protected final OrderService orderService; protected final String repositoryPrefix; protected DipBuilderService(DLCMProperties dlcmProperties, MessageService messageService, MetadataService metadataService, + OrderService orderService, DLCMRepositoryDescription repository) { super(messageService, dlcmProperties); this.metadataService = metadataService; + this.orderService = orderService; this.repositoryPrefix = repository.getName(); } @@ -85,6 +89,10 @@ public abstract class DipBuilderService extends DLCMService { public boolean createDipArchive(String orderLocation, Order order, String dipId, String orgUnitId, Access accessLevel, Path accessPath, Path dipFolder) throws IOException, JAXBException { final ZipTool zipTool; + if (this.orderService.isThereAnyOrderWithSameChecksum(order).isPresent()) { + return false; // Do not build DIP if there is already an order with the same checksum + } + // Create order archive (i.e. DIP) & Purge working files for each orgUnit zipTool = new ZipTool(this.getDipArchiveUri(orderLocation, order.getResId(), orgUnitId, accessLevel, dipId)); if (!zipTool.zipFiles(this.getBasePathToCreateDipZip(accessPath, order))) { @@ -107,11 +115,13 @@ public abstract class DipBuilderService extends DLCMService { } if (order.getSubsetItems() != null && !order.getSubsetItems().isEmpty() && !aip.isCollection()) { - this.buildSubsetDip(rootFolder.resolve(aip.getResId()), order.getSubsetItems()); - // Check that there is at least one data file apart from the internal folder - if (!isThereAtLeastOneFileInArchiveExcludingMetadataFolder(rootFolder.resolve(aip.getResId()))) { - log.error("IOException when checking if there is at least one file in the archive"); - throw new SolidifyRuntimeException("IOException when checking if there is at least one file in the archive"); + if (this.orderService.isThereAnyOrderWithSameChecksum(order).isEmpty()) { + this.buildSubsetDip(rootFolder.resolve(aip.getResId()), order.getSubsetItems()); + // Check that there is at least one data file apart from the internal folder + if (!isThereAtLeastOneFileInArchiveExcludingMetadataFolder(rootFolder.resolve(aip.getResId()))) { + log.error("IOException when checking if there is at least one file in the archive"); + throw new SolidifyRuntimeException("IOException when checking if there is at least one file in the archive"); + } } } this.buildDisseminationPolicyDip(rootFolder.resolve(aip.getResId()), aip, order); diff --git a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DisseminationPolicyProvider.java b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DisseminationPolicyProvider.java index 381174f125..c9226303a0 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DisseminationPolicyProvider.java +++ b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/DisseminationPolicyProvider.java @@ -23,13 +23,16 @@ package ch.dlcm.service.dissemination; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.stereotype.Service; +import ch.dlcm.controller.AccessController; import ch.dlcm.model.policies.DisseminationPolicy; import ch.dlcm.model.tool.CleanTool; import ch.dlcm.service.rest.trusted.TrustedDisseminationPolicyRemoteResourceService; @Service +@ConditionalOnBean(AccessController.class) public class DisseminationPolicyProvider { private final TrustedDisseminationPolicyRemoteResourceService disseminationPolicyRemoteResourceService; diff --git a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/HederaDipBuilderService.java b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/HederaDipBuilderService.java index 0a261f827d..c3747e19f3 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/HederaDipBuilderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/HederaDipBuilderService.java @@ -25,23 +25,28 @@ package ch.dlcm.service.dissemination; import java.nio.file.Path; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.stereotype.Service; import ch.unige.solidify.service.MessageService; +import ch.dlcm.business.OrderService; import ch.dlcm.config.DLCMProperties; import ch.dlcm.config.DLCMRepositoryDescription; +import ch.dlcm.controller.AccessController; import ch.dlcm.model.access.Order; import ch.dlcm.model.oais.ArchivalInfoPackage; import ch.dlcm.service.MetadataService; @Service +@ConditionalOnBean(AccessController.class) public class HederaDipBuilderService extends DipBuilderService { public HederaDipBuilderService(DLCMProperties dlcmProperties, MessageService messageService, MetadataService metadataService, + OrderService orderService, DLCMRepositoryDescription repository) { - super(dlcmProperties, messageService, metadataService, repository); + super(dlcmProperties, messageService, metadataService, orderService, repository); } @Override diff --git a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/IiifDipBuilderService.java b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/IiifDipBuilderService.java index e3b9b6f22c..71704e33ac 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/IiifDipBuilderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/IiifDipBuilderService.java @@ -33,6 +33,7 @@ import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.stereotype.Service; import org.springframework.util.AntPathMatcher; @@ -41,8 +42,10 @@ import ch.unige.solidify.service.MessageService; import ch.unige.solidify.util.FileTool; import ch.dlcm.DLCMConstants; +import ch.dlcm.business.OrderService; import ch.dlcm.config.DLCMProperties; import ch.dlcm.config.DLCMRepositoryDescription; +import ch.dlcm.controller.AccessController; import ch.dlcm.model.access.Order; import ch.dlcm.model.display.OrganizationalUnitDisseminationPolicyDTO; import ch.dlcm.model.oais.ArchivalInfoPackage; @@ -51,6 +54,7 @@ import ch.dlcm.service.rest.abstractservice.OrganizationalDisseminationPolicyRem import ch.dlcm.service.rest.trusted.TrustedOrganizationnalUnitDisseminationPolicyRemoteResourceService; @Service +@ConditionalOnBean(AccessController.class) public class IiifDipBuilderService extends DipBuilderService { private static final Logger log = LoggerFactory.getLogger(IiifDipBuilderService.class); @@ -62,9 +66,10 @@ public class IiifDipBuilderService extends DipBuilderService { public IiifDipBuilderService(DLCMProperties dlcmProperties, MessageService messageService, MetadataService metadataService, + OrderService orderService, DLCMRepositoryDescription repository, TrustedOrganizationnalUnitDisseminationPolicyRemoteResourceService trustedOrgUnitDisseminationPolicyRemoteService) { - super(dlcmProperties, messageService, metadataService, repository); + super(dlcmProperties, messageService, metadataService, orderService, repository); this.trustedOrgUnitDisseminationPolicyRemoteService = trustedOrgUnitDisseminationPolicyRemoteService; } diff --git a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/OaisDipBuilderService.java b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/OaisDipBuilderService.java index b925e04b91..3d0771f70b 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/OaisDipBuilderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/service/dissemination/OaisDipBuilderService.java @@ -26,6 +26,7 @@ package ch.dlcm.service.dissemination; import java.io.IOException; import java.nio.file.Path; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.stereotype.Service; import jakarta.xml.bind.JAXBException; @@ -35,21 +36,25 @@ import ch.unige.solidify.util.FileTool; import ch.unige.solidify.util.ZipTool; import ch.dlcm.DLCMConstants; +import ch.dlcm.business.OrderService; import ch.dlcm.config.DLCMProperties; import ch.dlcm.config.DLCMRepositoryDescription; +import ch.dlcm.controller.AccessController; import ch.dlcm.model.Access; import ch.dlcm.model.access.Order; import ch.dlcm.model.oais.ArchivalInfoPackage; import ch.dlcm.service.MetadataService; @Service +@ConditionalOnBean(AccessController.class) public class OaisDipBuilderService extends DipBuilderService { public OaisDipBuilderService(DLCMProperties dlcmProperties, MessageService messageService, MetadataService metadataService, + OrderService orderService, DLCMRepositoryDescription repository) { - super(dlcmProperties, messageService, metadataService, repository); + super(dlcmProperties, messageService, metadataService, orderService, repository); } @Override diff --git a/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java b/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java index 94787e9f81..dc548ec0ad 100644 --- a/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java +++ b/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java @@ -144,6 +144,10 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer @Column(name = DLCMConstants.ORGANIZATIONAL_DISSEMINATION_POLICY_ID_FIELD, length = DB_ID_LENGTH) private String organizationalUnitDisseminationPolicyId; + @Schema(description = "The checksum of the order subitems list.") + @Column(length = SolidifyConstants.DB_LONG_STRING_LENGTH) + private String checksum; + @Override public <T> boolean addItem(T t) { if (t instanceof DisseminationInfoPackage dip) { @@ -249,6 +253,10 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer return this.organizationalUnitDisseminationPolicyId; } + public String getChecksum() { + return this.checksum; + } + @JsonIgnore public boolean hasAipInError() { if (this.getAipPackages().isEmpty()) { @@ -409,6 +417,10 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer this.organizationalUnitDisseminationPolicyId = id; } + public void setChecksum(String checksum) { + this.checksum = checksum; + } + private boolean addAip(ArchivalInfoPackage aip) { if (!this.exist(this.aipPackages, aip)) { return this.aipPackages.add(aip); diff --git a/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql b/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql index d602318ca7..039247d34d 100755 --- a/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql +++ b/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql @@ -376,4 +376,8 @@ WHERE type IN ('IIIF') AND parameters IS NOT NULL; -update notification set sent_time = NOW() where sent_time is null; \ No newline at end of file +update notification set sent_time = NOW() where sent_time is null; + +-- add new column for order_queery to store checksum +ALTER TABLE order_query + ADD COLUMN checksum varchar(1024) null; \ No newline at end of file -- GitLab From 8d66a6b61ec26fa50c3e5bd9fb8ba514d828730b Mon Sep 17 00:00:00 2001 From: Homada Boumedane <homada.boumedane@unige.ch> Date: Wed, 19 Feb 2025 16:28:20 +0100 Subject: [PATCH 2/3] refactor: dissemination package fix code review. Closes: DLCM-2830 --- .../java/ch/dlcm/business/OrderService.java | 24 +++++--------- .../controller/access/SearchController.java | 33 ++++--------------- .../DisseminationInfoPackageRepository.java | 2 +- .../ch/dlcm/repository/OrderRepository.java | 6 ++-- .../main/java/ch/dlcm/model/access/Order.java | 11 +++---- .../main/resources/scripts/upgrade22to30.sql | 4 +-- 6 files changed, 27 insertions(+), 53 deletions(-) diff --git a/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java b/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java index 101887cc48..24b100e40e 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java @@ -35,6 +35,7 @@ import java.util.Optional; import java.util.stream.Collectors; import javax.xml.transform.TransformerFactoryConfigurationError; +import org.apache.logging.log4j.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -195,19 +196,16 @@ public class OrderService extends ResourceService<Order> { order.setQuery(aipId); order.setDisseminationPolicyId(disseminationPolicy.getDisseminationPolicyId()); order.setOrganizationalUnitDisseminationPolicyId(disseminationPolicy.getOrganizationalUnitDisseminationPolicyId()); - this.calculateChecksum(order, subsetItemList); //calculate and set checksum - final Order savedOrder = this.save(order); - if (subsetItemList == null) { // if no subsetItemList is provided, set it to an empty list subsetItemList = List.of(); } - + order.setSubitemsChecksum(this.calculateChecksum(subsetItemList)); //calculate and set checksum + final Order savedOrder = this.save(order); subsetItemList.forEach(subsetItem -> { subsetItem.setOrder(savedOrder); subsetItem.setCreatedBy(savedOrder.getCreatedBy()); subsetItem.setUpdatedBy(savedOrder.getUpdatedBy()); }); - this.orderSubsetItemRepository.saveAll(subsetItemList); return savedOrder; @@ -230,7 +228,7 @@ public class OrderService extends ResourceService<Order> { this.submitOrder(order1); } - public List<Order> findDirectOrderByAipAndDisseminationPolicy(String aipId, String disseminationPolicyId) { + public List<Order> findFullDirectOrderByAipAndDisseminationPolicy(String aipId, String disseminationPolicyId) { return ((OrderRepository) this.itemRepository).findFullDirectOrderByAipAndDisseminationPolicyId(aipId, disseminationPolicyId); } @@ -322,29 +320,25 @@ public class OrderService extends ResourceService<Order> { } public Optional<Order> isThereAnyOrderWithSameChecksum(Order order) { - return ((OrderRepository) this.itemRepository).findOrdersByChecksum(order.getChecksum(), order.getResId()) + return ((OrderRepository) this.itemRepository).findDifferentOrdersWithSameChecksum(order.getSubitemsChecksum(), order.getResId()) .stream() .findFirst(); } - private void calculateChecksum(Order order, List<OrderSubsetItem> subsetItems) { + public String calculateChecksum(List<OrderSubsetItem> subsetItems) { if (subsetItems != null && !subsetItems.isEmpty()) { // Create a string combining all paths, sorted by path to ensure consistent checksum String content = subsetItems.stream() .map(OrderSubsetItem::getItemPath) .sorted() - .collect(Collectors.joining("|")); - if (content.isEmpty()) { - order.setChecksum(null); - return; - } + .collect(Collectors.joining("")); try { - String hash = HashTool.hash(this.defaultChecksumAlgorithm.toString(), content.getBytes(StandardCharsets.UTF_8)); - order.setChecksum(hash); + return HashTool.hash(this.defaultChecksumAlgorithm.toString(), content.getBytes(StandardCharsets.UTF_8)); } catch (TransformerFactoryConfigurationError | NoSuchAlgorithmException e) { throw new SolidifyProcessingException(e.getMessage(), e); } } + return Strings.EMPTY; } @Override diff --git a/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java b/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java index 5afdcaf598..55cebaa31b 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java +++ b/DLCM-Access/src/main/java/ch/dlcm/controller/access/SearchController.java @@ -28,13 +28,9 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; -import java.util.stream.Collectors; -import javax.xml.transform.TransformerFactoryConfigurationError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,7 +56,6 @@ import ch.unige.solidify.SolidifyConstants; import ch.unige.solidify.auth.model.AuthApplicationRole; import ch.unige.solidify.auth.service.ApplicationRoleListService; import ch.unige.solidify.config.SolidifyEventPublisher; -import ch.unige.solidify.exception.SolidifyProcessingException; import ch.unige.solidify.exception.SolidifyRestException; import ch.unige.solidify.exception.SolidifyRuntimeException; import ch.unige.solidify.model.dto.CitationDto; @@ -72,7 +67,6 @@ import ch.unige.solidify.security.EveryonePermissions; import ch.unige.solidify.service.DownloadTokenService; import ch.unige.solidify.service.rest.abstractservice.IndexMetadataRemoteResourceService; import ch.unige.solidify.util.FileTool; -import ch.unige.solidify.util.HashTool; import ch.unige.solidify.util.StringTool; import ch.dlcm.DLCMConstants; @@ -84,7 +78,6 @@ import ch.dlcm.message.ArchiveStatisticMessage.StatisticType; import ch.dlcm.model.MetadataVisibility; import ch.dlcm.model.access.Order; import ch.dlcm.model.access.Order.OrderStatus; -import ch.dlcm.model.access.OrderSubsetItem; import ch.dlcm.model.dto.DisseminationPolicyDto; import ch.dlcm.model.index.ArchiveMetadata; import ch.dlcm.model.oais.DisseminationInfoPackage; @@ -176,7 +169,7 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro DisseminationPolicy disseminationPolicy; if (orderId == null) { //If order is not specified, check a direct order with the aipId as dipName and disseminationPolicyPublic and not itemList selected. - List<Order> orderList = this.orderService.findDirectOrderByAipAndDisseminationPolicy(dipName, + List<Order> orderList = this.orderService.findFullDirectOrderByAipAndDisseminationPolicy(dipName, DISSEMINATION_POLICY_BASIC_ID); if (orderList.isEmpty()) { throw new IllegalStateException("Order for DIP " + dipName + " is missing"); @@ -245,7 +238,7 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro boolean isBasicPolicy = disseminationPolicyDto.getDisseminationPolicyId().equals(DISSEMINATION_POLICY_BASIC_ID); if (isBasicPolicy && disseminationPolicyDto.getSubsetItemList() != null) { // Basic policy with subset items - find specific DIP - String hash = this.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); + String hash = this.orderService.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); dipList = this.dipRepository.findByDisseminationPolicyIdAndAipIdAndSubsetItems(disseminationPolicyDto.getDisseminationPolicyId(), aipId, hash); } else { @@ -261,17 +254,18 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro if (dipList.isEmpty()) { // No DIP found // Check if the DTO has asked for subset items - if (disseminationPolicyDto.getSubsetItemList() != null) { + if (disseminationPolicyDto.getSubsetItemList() != null || disseminationPolicyDto.getSubsetItemList().isEmpty()) { // calculate checksum of subset items - String hash = this.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); + String hash = this.orderService.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); directOrders = isBasicPolicy ? orderService.findDirectOrderByDisseminationPolicyAndSubsetChecksum(aipId, disseminationPolicyDto.getDisseminationPolicyId(), hash) : - orderService.findDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); + orderService.findFullDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); } else { - directOrders = this.orderService.findDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); + directOrders = this.orderService.findFullDirectOrderByAipAndDisseminationPolicy(aipId, + disseminationPolicyDto.getDisseminationPolicyId()); } if (directOrders.isEmpty()) { @@ -398,17 +392,4 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro final ArchiveMetadata archive = this.getIndexResourceRemoteService().getIndexMetadata(dipName); return this.disseminationPolicyProvider.calculateFinalFileName(disseminationPolicy, archive.getTitle(), dipName); } - - private String calculateChecksum(List<OrderSubsetItem> subsetItems) { - // Create a string combining all paths, sorted by path to ensure consistent checksum - String content = subsetItems.stream() - .map(OrderSubsetItem::getItemPath) - .sorted() - .collect(Collectors.joining("|")); - try { - return HashTool.hash(this.defaultChecksumAlgorithm.toString(), content.getBytes(StandardCharsets.UTF_8)); - } catch (TransformerFactoryConfigurationError | NoSuchAlgorithmException e) { - throw new SolidifyProcessingException(e.getMessage(), e); - } - } } diff --git a/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java b/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java index 596ba28aba..c2af5cd4c2 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java +++ b/DLCM-Access/src/main/java/ch/dlcm/repository/DisseminationInfoPackageRepository.java @@ -77,6 +77,6 @@ public interface DisseminationInfoPackageRepository extends SolidifyRepository<D + "AND order.queryType = 'DIRECT'") List<DisseminationInfoPackage> findByFullDisseminationPolicyIdAndAipId(String disseminationPolicyId, String aipId); - @Query("SELECT dip FROM DisseminationInfoPackage dip JOIN dip.orders order JOIN dip.aips aip WHERE aip.resId = :aipId AND order.disseminationPolicyId = :disseminationPolicyId AND order.checksum = :checksum") + @Query("SELECT dip FROM DisseminationInfoPackage dip JOIN dip.orders order JOIN dip.aips aip WHERE aip.resId = :aipId AND order.disseminationPolicyId = :disseminationPolicyId AND order.subitemsChecksum = :checksum") List<DisseminationInfoPackage> findByDisseminationPolicyIdAndAipIdAndSubsetItems(String disseminationPolicyId, String aipId, String checksum); } diff --git a/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java b/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java index b23b1e2e90..d7c7c260ae 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java +++ b/DLCM-Access/src/main/java/ch/dlcm/repository/OrderRepository.java @@ -54,7 +54,7 @@ public interface OrderRepository extends SolidifyRepository<Order> { @Query("SELECT DISTINCT o FROM Order o JOIN o.aipPackages aip LEFT JOIN o.subsetItems si WHERE aip.resId=:aipId and o.queryType = 'DIRECT' and o.disseminationPolicyId=:disseminationPolicyId and si IS NULL") List<Order> findFullDirectOrderByAipAndDisseminationPolicyId(String aipId, String disseminationPolicyId); - @Query("SELECT DISTINCT o FROM Order o JOIN o.aipPackages aip WHERE aip.resId=:aipId and o.queryType = 'DIRECT' and o.disseminationPolicyId=:disseminationPolicyId and o.checksum =:checksum") + @Query("SELECT DISTINCT o FROM Order o JOIN o.aipPackages aip WHERE aip.resId=:aipId and o.queryType = 'DIRECT' and o.disseminationPolicyId=:disseminationPolicyId and o.subitemsChecksum =:checksum") List<Order> findDirectOrderByDisseminationPolicyIdAndAipIdAndChecksum(String aipId, String disseminationPolicyId, String checksum); List<Order> findByStatusIn(List<OrderStatus> statuses); @@ -69,7 +69,7 @@ public interface OrderRepository extends SolidifyRepository<Order> { * @param orderId the order ID to exclude from search * @return list of orders with matching checksums */ - @Query("SELECT o FROM Order o WHERE o.checksum = :checksum AND o.resId != :orderId ORDER BY o.creation.when DESC") - List<Order> findOrdersByChecksum(String checksum, String orderId); + @Query("SELECT o FROM Order o WHERE o.subitemsChecksum = :checksum AND o.resId != :orderId ORDER BY o.creation.when DESC") + List<Order> findDifferentOrdersWithSameChecksum(String checksum, String orderId); } diff --git a/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java b/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java index dc548ec0ad..17dbe5a463 100644 --- a/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java +++ b/DLCM-Model/src/main/java/ch/dlcm/model/access/Order.java @@ -145,8 +145,7 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer private String organizationalUnitDisseminationPolicyId; @Schema(description = "The checksum of the order subitems list.") - @Column(length = SolidifyConstants.DB_LONG_STRING_LENGTH) - private String checksum; + private String subitemsChecksum; @Override public <T> boolean addItem(T t) { @@ -253,8 +252,8 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer return this.organizationalUnitDisseminationPolicyId; } - public String getChecksum() { - return this.checksum; + public String getSubitemsChecksum() { + return this.subitemsChecksum; } @JsonIgnore @@ -417,8 +416,8 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer this.organizationalUnitDisseminationPolicyId = id; } - public void setChecksum(String checksum) { - this.checksum = checksum; + public void setSubitemsChecksum(String checksum) { + this.subitemsChecksum = checksum; } private boolean addAip(ArchivalInfoPackage aip) { diff --git a/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql b/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql index 039247d34d..d00fb89bb6 100755 --- a/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql +++ b/DLCM-Model/src/main/resources/scripts/upgrade22to30.sql @@ -378,6 +378,6 @@ WHERE type IN ('IIIF') update notification set sent_time = NOW() where sent_time is null; --- add new column for order_queery to store checksum +-- add new column for order_query to store checksum ALTER TABLE order_query - ADD COLUMN checksum varchar(1024) null; \ No newline at end of file + ADD COLUMN checksum varchar(255) null; \ No newline at end of file -- GitLab From 59d0941c4f5fc4ec8f9ae10e3486ec321287aa23 Mon Sep 17 00:00:00 2001 From: Homada Boumedane <homada.boumedane@unige.ch> Date: Wed, 19 Feb 2025 17:08:56 +0100 Subject: [PATCH 3/3] refactor: dissemination package fix code review. Closes: DLCM-2830 --- DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java b/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java index 24b100e40e..bff2783dc2 100644 --- a/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java +++ b/DLCM-Access/src/main/java/ch/dlcm/business/OrderService.java @@ -35,7 +35,6 @@ import java.util.Optional; import java.util.stream.Collectors; import javax.xml.transform.TransformerFactoryConfigurationError; -import org.apache.logging.log4j.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -338,7 +337,7 @@ public class OrderService extends ResourceService<Order> { throw new SolidifyProcessingException(e.getMessage(), e); } } - return Strings.EMPTY; + return ""; } @Override -- GitLab