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 16702c51504fba1d02ae06d5fb28d2a95f2ade3d..bff2783dc24d325310f309b39a57be853d43b7e7 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,24 @@ 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()); + 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); - List<OrderSubsetItem> subsetItemList = disseminationPolicy.getSubsetItemList(); subsetItemList.forEach(subsetItem -> { subsetItem.setOrder(savedOrder); subsetItem.setCreatedBy(savedOrder.getCreatedBy()); subsetItem.setUpdatedBy(savedOrder.getUpdatedBy()); }); this.orderSubsetItemRepository.saveAll(subsetItemList); + return savedOrder; } @@ -216,6 +231,11 @@ public class OrderService extends ResourceService<Order> { 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 +318,28 @@ public class OrderService extends ResourceService<Order> { return ((OrderRepository) this.itemRepository).getSize(resId); } + public Optional<Order> isThereAnyOrderWithSameChecksum(Order order) { + return ((OrderRepository) this.itemRepository).findDifferentOrdersWithSameChecksum(order.getSubitemsChecksum(), order.getResId()) + .stream() + .findFirst(); + } + + 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("")); + try { + return HashTool.hash(this.defaultChecksumAlgorithm.toString(), content.getBytes(StandardCharsets.UTF_8)); + } catch (TransformerFactoryConfigurationError | NoSuchAlgorithmException e) { + throw new SolidifyProcessingException(e.getMessage(), e); + } + } + return ""; + } + @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 f1a8ba0e7268837c008d2e99ff41db3cd6cd1b25..55cebaa31b02394820cfa43865dbcddead7bba52 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,6 +23,7 @@ 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; @@ -50,6 +51,7 @@ 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; @@ -100,6 +102,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 +122,7 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro this.downloadTokenService = downloadTokenService; this.trustedUserRemoteResourceService = trustedUserRemoteResourceService; this.disseminationPolicyProvider = disseminationPolicyProvider; + this.defaultChecksumAlgorithm = ChecksumAlgorithm.valueOf(dlcmProperties.getParameters().getDefaultChecksum()); } @Override @@ -166,7 +170,7 @@ public abstract class SearchController extends AccessIndexResourceReadOnlyContro 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); + DISSEMINATION_POLICY_BASIC_ID); if (orderList.isEmpty()) { throw new IllegalStateException("Order for DIP " + dipName + " is missing"); } @@ -221,61 +225,78 @@ 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.orderService.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 || disseminationPolicyDto.getSubsetItemList().isEmpty()) { + // calculate checksum of subset items + String hash = this.orderService.calculateChecksum(disseminationPolicyDto.getSubsetItemList()); + directOrders = isBasicPolicy + ? + orderService.findDirectOrderByDisseminationPolicyAndSubsetChecksum(aipId, disseminationPolicyDto.getDisseminationPolicyId(), + hash) + : + orderService.findFullDirectOrderByAipAndDisseminationPolicy(aipId, disseminationPolicyDto.getDisseminationPolicyId()); + } else { + directOrders = this.orderService.findFullDirectOrderByAipAndDisseminationPolicy(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 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 1ff12dd3316ad487b2ba234d5cfaa64c6d4a9061..c2af5cd4c2188e257dfe31cdb0bf48345dc94f6a 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.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 09771e5e8a558bcfb340abf008f9cfbbdf81d5a5..d7c7c260ae47ae7d3aabd20c0f1ad13523107ef8 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.subitemsChecksum =: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.subitemsChecksum = :checksum AND o.resId != :orderId ORDER BY o.creation.when DESC") + List<Order> findDifferentOrdersWithSameChecksum(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 6c38ce505eed7bbe0d999716fde623c870bb6cef..1868ebce6bb5f23911164fd4f2fef5cd94a79bbf 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 94cf9494fc7f366db3cd3a72dff2bd944d7eb4f8..8c38a64ea5b2c726f2b5a8c203ea2aab271f305d 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 381174f1251d3e11f3f2df6177636700379e0b15..c9226303a04df92a14ea63060749d85e2e7a5315 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 0a261f827dd7b974604083408c85cc485f285d56..c3747e19f32c099afa1428dd297b02d8d13ed943 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 e3b9b6f22c86f6dc8d45b0a7d51db8620b893e08..71704e33ac4294f303c01605df8d28b35339580e 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 b925e04b91ca5cdc14710fd3dd6e836b254f73a7..3d0771f70bc193c8ce89059bbec418df6e161988 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 94787e9f81b76f0262398a0abbd4dc52e86098bb..17dbe5a463d327c9ce997c075928b67cdb3f55f2 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,9 @@ 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.") + private String subitemsChecksum; + @Override public <T> boolean addItem(T t) { if (t instanceof DisseminationInfoPackage dip) { @@ -249,6 +252,10 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer return this.organizationalUnitDisseminationPolicyId; } + public String getSubitemsChecksum() { + return this.subitemsChecksum; + } + @JsonIgnore public boolean hasAipInError() { if (this.getAipPackages().isEmpty()) { @@ -409,6 +416,10 @@ public class Order extends ResourceNormalized implements RemoteResourceContainer this.organizationalUnitDisseminationPolicyId = id; } + public void setSubitemsChecksum(String checksum) { + this.subitemsChecksum = 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 d602318ca77e029d39c2b2a205fab15798e9c02a..d00fb89bb63493b304ff0381820a88ddcf743b11 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_query to store checksum +ALTER TABLE order_query + ADD COLUMN checksum varchar(255) null; \ No newline at end of file