diff --git a/vorgang-manager-interface/src/main/protobuf/file.model.proto b/vorgang-manager-interface/src/main/protobuf/file.model.proto index 0e82120cb1870ae28f60ebd314d6257b76178042..c78f2f8332f50132ac678dd60734fcf9e6efbe1e 100644 --- a/vorgang-manager-interface/src/main/protobuf/file.model.proto +++ b/vorgang-manager-interface/src/main/protobuf/file.model.proto @@ -32,16 +32,19 @@ option java_outer_classname = "FileModelProto"; message GrpcGetAttachmentsRequest { - de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1; + de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1 [deprecated = true]; string eingangId = 2; + string vorgangId = 3; } + message GrpcGetAttachmentsResponse { repeated GrpcOzgFile file = 1; } message GrpcGetRepresentationsRequest { - de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1; + de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1 [deprecated = true]; string eingangId = 2; + string vorgangId = 3; } message GrpcGetRepresentationsResponse { repeated GrpcOzgFile file = 1; diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java index c572496f9c31df5739bcfa42f89542490b0bc8aa..59d74b21eb13b52448739efa9db3872f2d6100ac 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java @@ -25,6 +25,7 @@ package de.ozgcloud.vorgang.files; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; @@ -33,6 +34,7 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.stereotype.Repository; +import de.ozgcloud.vorgang.common.db.CriteriaUtil; import de.ozgcloud.vorgang.vorgang.Vorgang; @Repository @@ -41,61 +43,62 @@ class EingangFilesRepository { @Autowired private MongoTemplate mongoTemplate; - private static final String DB_FIELDNAME_EINGANG_ID = "eingangs._id"; private static final String DB_FIELDNAME_EINGANGS = "eingangs"; - private static final String DB_FIELDNAME_ATTACHMENTS = "attachments"; + private static final String FIELD_EINGANG_ID = DB_FIELDNAME_EINGANGS + "._id"; private static final String DB_FIELDNAME_FILES = "files"; - private static final String DB_FIELDNAME_REPRESENTATIONS = "representations"; + private static final String FIELD_ATTACHMENT_FILES = DB_FIELDNAME_EINGANGS + ".attachments." + DB_FIELDNAME_FILES; + private static final String FIELD_REPRESENTATION_FILES = DB_FIELDNAME_EINGANGS + ".representations"; - private static final String DB_FIELDNAME_FILE_ID = "id"; - private static final String DB_FIELDNAME_FILE_NAME = "name"; - private static final String DB_FIELDNAME_FILE_SIZE = "size"; - private static final String DB_FIELDNAME_FILE_CONTENT_TYPE = "contentType"; + public List<OzgFile> findAttachments(Optional<String> vorgangId, Optional<String> eingangId) { + return findFiles(buildSearchCriteria(vorgangId, eingangId), buildExtractAttachmentsAggregation()); + } - public List<OzgFile> findAttachmentsByEingangId(String eingangId) { + private List<AggregationOperation> buildExtractAttachmentsAggregation() { + return List.of( + Aggregation.project().andExpression(FIELD_ATTACHMENT_FILES).as(DB_FIELDNAME_FILES), // + // extract 'files' from deeply nested arrays within 'eingangs[].attachments[].files[]' and promote each file to a separate document + // at the root level. + Aggregation.unwind(DB_FIELDNAME_FILES), + Aggregation.unwind(DB_FIELDNAME_FILES), + Aggregation.unwind(DB_FIELDNAME_FILES), + Aggregation.replaceRoot(DB_FIELDNAME_FILES) + ); + } - List<AggregationOperation> operations = new ArrayList<>(); + public List<OzgFile> findRepresentations(Optional<String> vorgangId, Optional<String> eingangId) { + return findFiles(buildSearchCriteria(vorgangId, eingangId), buildFindRepresentationsAggregation()); + } - operations.add(Aggregation.match(new Criteria(DB_FIELDNAME_EINGANG_ID).is(eingangId))); - operations.addAll(buildFindAttachmentsAggregation()); - operations.add(Aggregation.project(DB_FIELDNAME_FILE_ID, DB_FIELDNAME_FILE_NAME, DB_FIELDNAME_FILE_SIZE, DB_FIELDNAME_FILE_CONTENT_TYPE)); + private Criteria buildSearchCriteria(Optional<String> vorgangId, Optional<String> eingangId) { + if (vorgangId.isEmpty()) { + return eingangId.map(this::buildIsEingangIdCriteria) + .orElseThrow(() -> new IllegalArgumentException("vorgangId or eingangId must be present")); + } + return eingangId.map(eid -> buildIsVorganIdAndEingangIdCriteria(vorgangId.get(), eid)).orElseGet(() -> CriteriaUtil.isId(vorgangId.get())); + } - return mongoTemplate.aggregate(Aggregation.newAggregation(operations), Vorgang.COLLECTION_NAME, OzgFile.class).getMappedResults(); + private Criteria buildIsVorganIdAndEingangIdCriteria(String vorgangId, String eingangId) { + return new Criteria().andOperator(CriteriaUtil.isId(vorgangId), buildIsEingangIdCriteria(eingangId)); } - private List<AggregationOperation> buildFindAttachmentsAggregation() { + private Criteria buildIsEingangIdCriteria(String eingangId) { + return Criteria.where(FIELD_EINGANG_ID).is(eingangId); + } + private List<AggregationOperation> buildFindRepresentationsAggregation() { return List.of( - Aggregation.project(DB_FIELDNAME_EINGANGS), - Aggregation.unwind(DB_FIELDNAME_EINGANGS), - Aggregation.replaceRoot(DB_FIELDNAME_EINGANGS), - Aggregation.project(DB_FIELDNAME_ATTACHMENTS), - Aggregation.unwind(DB_FIELDNAME_ATTACHMENTS), - Aggregation.replaceRoot(DB_FIELDNAME_ATTACHMENTS), - Aggregation.project(DB_FIELDNAME_FILES), + Aggregation.project().andExpression(FIELD_REPRESENTATION_FILES).as(DB_FIELDNAME_FILES), + // extract 'files' from deeply nested arrays within 'eingangs[].representations[]' and promote each file to a separate document at + // the root level. + Aggregation.unwind(DB_FIELDNAME_FILES), Aggregation.unwind(DB_FIELDNAME_FILES), Aggregation.replaceRoot(DB_FIELDNAME_FILES)); } - List<OzgFile> findRepresentationsByEingangId(String eingangId) { - + private List<OzgFile> findFiles(Criteria criteria, List<AggregationOperation> extractOperations) { List<AggregationOperation> operations = new ArrayList<>(); - - operations.add(Aggregation.match(new Criteria(DB_FIELDNAME_EINGANG_ID).is(eingangId))); - operations.addAll(buildFindRepresentationsAggregation()); - operations.add(Aggregation.project(DB_FIELDNAME_FILE_ID, DB_FIELDNAME_FILE_NAME, DB_FIELDNAME_FILE_SIZE, DB_FIELDNAME_FILE_CONTENT_TYPE)); - + operations.add(Aggregation.match(criteria)); + operations.addAll(extractOperations); return mongoTemplate.aggregate(Aggregation.newAggregation(operations), Vorgang.COLLECTION_NAME, OzgFile.class).getMappedResults(); } - - private List<AggregationOperation> buildFindRepresentationsAggregation() { - - return List.of( - Aggregation.project(DB_FIELDNAME_EINGANGS), - Aggregation.unwind(DB_FIELDNAME_EINGANGS), - Aggregation.replaceRoot(DB_FIELDNAME_EINGANGS), - Aggregation.project(DB_FIELDNAME_REPRESENTATIONS), - Aggregation.unwind(DB_FIELDNAME_REPRESENTATIONS), - Aggregation.replaceRoot(DB_FIELDNAME_REPRESENTATIONS)); - } } diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java index 0d7b3bce1e8afec53d0c9a0cf082376d95f31b1c..e25b2e81b6aa1069e098ff4351b344a460f8e8d6 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java @@ -52,12 +52,12 @@ public class FileService implements BinaryFileService { @Autowired private FileIdMapper fileIdMapper; - public List<OzgFile> getAttachments(String eingangId) { - return repository.findAttachmentsByEingangId(eingangId); + public List<OzgFile> getAttachments(Optional<String> vorgangId, Optional<String> eingangId) { + return repository.findAttachments(vorgangId, eingangId); } - public List<OzgFile> getRepresentations(String eingangId) { - return repository.findRepresentationsByEingangId(eingangId); + public List<OzgFile> getRepresentations(Optional<String> vorgangId, Optional<String> eingangId) { + return repository.findRepresentations(vorgangId, eingangId); } public FileId uploadFileStream(UploadedFilesReference ref, OzgFile file, Optional<String> userId, InputStream content) { diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java index aecb28e71a31a57da6758eb530b96dfbc82590f4..6a37c045769c03c3520b0c0b4f043d22e64780d5 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java @@ -24,7 +24,9 @@ package de.ozgcloud.vorgang.files; import java.util.List; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import de.ozgcloud.vorgang.grpc.file.FileServiceGrpc.FileServiceImplBase; @@ -46,17 +48,33 @@ public class GrpcFileService extends FileServiceImplBase { @Override public void getAttachments(GrpcGetAttachmentsRequest request, StreamObserver<GrpcGetAttachmentsResponse> responseObserver) { - List<OzgFile> response = service.getAttachments(request.getEingangId()); + List<OzgFile> response = service.getAttachments(getVorgangId(request), getEingangId(request)); responseObserver.onNext(GrpcGetAttachmentsResponse.newBuilder().addAllFile(fileMapper.map(response)).build()); responseObserver.onCompleted(); } + private Optional<String> getVorgangId(GrpcGetAttachmentsRequest request) { + return Optional.of(request.getVorgangId()).map(StringUtils::trimToNull); + } + + private Optional<String> getEingangId(GrpcGetAttachmentsRequest request) { + return Optional.of(request.getEingangId()).map(StringUtils::trimToNull); + } + @Override public void getRepresentations(GrpcGetRepresentationsRequest request, StreamObserver<GrpcGetRepresentationsResponse> responseObserver) { - List<OzgFile> response = service.getRepresentations(request.getEingangId()); + List<OzgFile> response = service.getRepresentations(getVorgangId(request), getEingangId(request)); responseObserver.onNext(GrpcGetRepresentationsResponse.newBuilder().addAllFile(fileMapper.map(response)).build()); responseObserver.onCompleted(); } + + private Optional<String> getVorgangId(GrpcGetRepresentationsRequest request) { + return Optional.of(request.getVorgangId()).map(StringUtils::trimToNull); + } + + private Optional<String> getEingangId(GrpcGetRepresentationsRequest request) { + return Optional.of(request.getEingangId()).map(StringUtils::trimToNull); + } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java index 0159d03a6f45f5a725e8ef49a6047bd6747c45c3..de2c1ee0f64abd28e39b2953d9902692db1f84c1 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java @@ -26,6 +26,8 @@ package de.ozgcloud.vorgang.files; import static org.assertj.core.api.Assertions.*; import java.util.List; +import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -61,27 +63,107 @@ class EingangFilesRepositoryITCase { mongoOperations.save(createVorgang()); } - @Test - void shouldHaveTwoAttachments() { - List<OzgFile> attachments = repository.findAttachmentsByEingangId(EingangTestFactory.ID); + @Nested + class TestByEingangId { - assertThat(attachments).hasSize(2); + @Test + void shouldHaveTwoAttachments() { + var attachments = findAttachments(); + + assertThat(attachments).hasSize(2); + } + + @Test + void validateFirstAttachment() { + OzgFile attachment = findAttachments().get(0); + + assertThat(attachment.getId()).isEqualTo(IncomingFileTestFactory.ID); + assertThat(attachment.getName()).isEqualTo(IncomingFileTestFactory.NAME); + assertThat(attachment.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + } + + @Test + void validateSecondAttachment() { + var attachment = findAttachments().get(1); + + assertThat(attachment.getId()).isEqualTo(ID2); + } + + private List<OzgFile> findAttachments() { + return repository.findAttachments(Optional.empty(), Optional.of(EingangTestFactory.ID)); + } } - @Test - void validateFirstAttachment() { - OzgFile attachment = repository.findAttachmentsByEingangId(EingangTestFactory.ID).get(0); + @Nested + class TestByVorgangId { + + @Test + void shouldFindWhenOneEingang() { + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).build()); + + var result = findAttachments(vorgang.getId()); + + assertThat(result).hasSize(1); + } + + @Test + void shouldFindWhenManyEingangs() { + var vorang = mongoOperations.save( + VorgangTestFactory.createBuilder().id(null).version(0L).clearEingangs() + .eingang(EingangTestFactory.createBuilder().id(UUID.randomUUID().toString()).clearAttachments() + .attachment(IncomingFileGroupTestFactory.createBuilder().clearFiles().files(createTestFiles()).build()) + .build()) + .eingang(EingangTestFactory.createBuilder().id(UUID.randomUUID().toString()).clearAttachments() + .attachment(IncomingFileGroupTestFactory.create()) + .attachment(IncomingFileGroupTestFactory.create()) + .build()) + .build()); - assertThat(attachment.getId()).isEqualTo(IncomingFileTestFactory.ID); - assertThat(attachment.getName()).isEqualTo(IncomingFileTestFactory.NAME); - assertThat(attachment.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + var result = findAttachments(vorang.getId()); + + assertThat(result).hasSize(4); + } + + @Test + void shouldReturnEmpty() { + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).clearEingangs() + .eingang(EingangTestFactory.createBuilder().clearAttachments().build()).build()); + + var result = findAttachments(vorgang.getId()); + + assertThat(result).isEmpty(); + } + + private List<OzgFile> findAttachments(String vorgangId) { + return repository.findAttachments(Optional.of(vorgangId), Optional.empty()); + } } - @Test - void validateSecondAttachment() { - OzgFile attachment = repository.findAttachmentsByEingangId(EingangTestFactory.ID).get(1); + @Nested + class TestByVorgangIdAndEingangId { + + @Test + void shouldReturnEmpty() { + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).build()); + + var result = repository.findAttachments(Optional.ofNullable(vorgang.getId()), Optional.of("not-existing")); + + assertThat(result).isEmpty(); + } + + @Test + void shouldFindAttachments() { + var eingangId = UUID.randomUUID().toString(); + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).clearEingangs() + .eingang(EingangTestFactory.createBuilder().id(eingangId) + .attachment(IncomingFileGroupTestFactory.createBuilder().clearFiles().files(createTestFiles()).build()) + .build()) + .build()); + + var result = repository.findAttachments(Optional.ofNullable(vorgang.getId()), Optional.ofNullable(eingangId)); - assertThat(attachment.getId()).isEqualTo(ID2); + assertThat(result).hasSize(3); + } } } @@ -96,29 +178,106 @@ class EingangFilesRepositoryITCase { mongoOperations.save(vorgangWithRepresentations); } - @Test - void shouldHaveTwoRepresentations() { - List<OzgFile> representations = repository.findRepresentationsByEingangId(EingangTestFactory.ID); + @Nested + class TestByEingangId { - assertThat(representations).hasSize(2); + @Test + void shouldHaveTwoRepresentations() { + List<OzgFile> representations = findRepresentations(); + + assertThat(representations).hasSize(2); + } + + @Test + void validateFirstRepresentation() { + OzgFile representation = findRepresentations().get(0); + + assertThat(representation.getId()).isEqualTo(IncomingFileTestFactory.ID); + assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); + assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + } + + @Test + void validateSecondRepresentation() { + OzgFile representation = findRepresentations().get(1); + + assertThat(representation.getId()).isEqualTo(ID2); + assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); + assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + } + + private List<OzgFile> findRepresentations() { + return repository.findRepresentations(Optional.empty(), Optional.of(EingangTestFactory.ID)); + } } - @Test - void validateFirstRepresentation() { - OzgFile representation = repository.findRepresentationsByEingangId(EingangTestFactory.ID).get(0); + @Nested + class TestByVorgangId { + + @Test + void shouldFindWhenOneEingang() { + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).build()); + + var result = findRepresentations(vorgang.getId()); + + assertThat(result).hasSize(1); + } + + @Test + void shouldFindWhenManyEingangs() { + var vorang = mongoOperations.save( + VorgangTestFactory.createBuilder().id(null).version(0L).clearEingangs() + .eingang(EingangTestFactory.createBuilder().id(UUID.randomUUID().toString()).clearRepresentations() + .representation(IncomingFileTestFactory.create()) + .representation(IncomingFileTestFactory.create()) + .build()) + .eingang(EingangTestFactory.createBuilder().id(UUID.randomUUID().toString()).clearRepresentations() + .representation(IncomingFileTestFactory.create()) + .build()) + .build()); - assertThat(representation.getId()).isEqualTo(IncomingFileTestFactory.ID); - assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); - assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + var result = findRepresentations(vorang.getId()); + + assertThat(result).hasSize(3); + } + + @Test + void shouldReturnEmpty() { + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).clearEingangs() + .eingang(EingangTestFactory.createBuilder().clearRepresentations().build()).build()); + + var result = findRepresentations(vorgang.getId()); + + assertThat(result).isEmpty(); + } + + private List<OzgFile> findRepresentations(String vorgangId) { + return repository.findRepresentations(Optional.of(vorgangId), Optional.empty()); + } } - @Test - void validateSecondRepresentation() { - OzgFile representation = repository.findRepresentationsByEingangId(EingangTestFactory.ID).get(1); + @Nested + class TestByVorgangIdAndEingangId { + + @Test + void shouldReturnEmpty() { + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).build()); + + var result = repository.findAttachments(Optional.of(vorgang.getId()), Optional.of("not-existing")); + + assertThat(result).isEmpty(); + } + + @Test + void shouldFindRepresentations() { + var eingangId = UUID.randomUUID().toString(); + var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).clearEingangs() + .eingang(EingangTestFactory.createBuilder().id(eingangId).representation(IncomingFileTestFactory.create()).build()).build()); + + var result = repository.findRepresentations(Optional.ofNullable(vorgang.getId()), Optional.ofNullable(eingangId)); - assertThat(representation.getId()).isEqualTo(ID2); - assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); - assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + assertThat(result).hasSize(2); + } } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java index a4174aa6923d32d4a7ef2b78f67e56c9a0f8f2b6..723386437a009867bf558656f2b9cf1c7d7bfc17 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java @@ -83,44 +83,88 @@ class FileITCase { private StreamObserver<GrpcGetAttachmentsResponse> responseObserver; @Captor private ArgumentCaptor<GrpcGetAttachmentsResponse> responseCaptor; - private GrpcGetAttachmentsRequest request = GrpcGetAttachmentsRequestTestFactory.create(); - @Test - void getAttachmentsShouldReturnNonEmptyGrpcResponse() { - callServiceGetAttachments(); + private GrpcGetAttachmentsRequest request; - var grpcResponse = responseCaptor.getValue(); + @Nested + class TestByEingangId { - assertThat(grpcResponse).isNotNull(); - } + @BeforeEach + void init() { + request = GrpcGetAttachmentsRequestTestFactory.createBuilder().clearVorgangId().build(); + } - @Test - void eingangShouldHaveTwoAttachments() { - callServiceGetAttachments(); + @Test + void getAttachmentsShouldReturnNonEmptyGrpcResponse() { + callServiceGetAttachments(); - var grpcResponse = responseCaptor.getValue(); + var grpcResponse = responseCaptor.getValue(); - assertThat(grpcResponse.getFileCount()).isEqualTo(2); + assertThat(grpcResponse).isNotNull(); + } + + @Test + void eingangShouldHaveTwoAttachments() { + callServiceGetAttachments(); + + var grpcResponse = responseCaptor.getValue(); + + assertThat(grpcResponse.getFileCount()).isEqualTo(2); + } + + @Test + void validateFirstAttachmentFileContent() { + callServiceGetAttachments(); + + var attachment1 = responseCaptor.getValue().getFile(0); + + assertThat(attachment1.getId()).isEqualTo(IncomingFileTestFactory.ID.toString()); + assertThat(attachment1.getName()).isEqualTo(IncomingFileTestFactory.NAME); + assertThat(attachment1.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + } + + @Test + void validateSecondAttachmentFileContent() { + callServiceGetAttachments(); + + var attachment2 = responseCaptor.getValue().getFile(1); + + assertThat(attachment2.getId()).isEqualTo(ID2.toString()); + } } - @Test - void validateFirstAttachmentFileContent() { - callServiceGetAttachments(); + @Nested + class TestByVorgangId { - var attachment1 = responseCaptor.getValue().getFile(0); + @BeforeEach + void init() { + request = GrpcGetAttachmentsRequestTestFactory.createBuilder().clearEingangId().build(); + } - assertThat(attachment1.getId()).isEqualTo(IncomingFileTestFactory.ID.toString()); - assertThat(attachment1.getName()).isEqualTo(IncomingFileTestFactory.NAME); - assertThat(attachment1.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + @Test + void shouldGetAttachments() { + callServiceGetAttachments(); + + verify(responseObserver).onNext(responseCaptor.capture()); + assertThat(responseCaptor.getValue().getFileCount()).isEqualTo(2); + } } - @Test - void validateSecondAttachmentFileContent() { - callServiceGetAttachments(); + @Nested + class TestByVorgangAndEingangId { - var attachment1 = responseCaptor.getValue().getFile(1); + @BeforeEach + void init() { + request = GrpcGetAttachmentsRequestTestFactory.create(); + } - assertThat(attachment1.getId()).isEqualTo(ID2.toString()); + @Test + void shouldGetAttachments() { + callServiceGetAttachments(); + + verify(responseObserver).onNext(responseCaptor.capture()); + assertThat(responseCaptor.getValue().getFileCount()).isEqualTo(2); + } } private void callServiceGetAttachments() { @@ -137,7 +181,7 @@ class FileITCase { private StreamObserver<GrpcGetRepresentationsResponse> responseObserver; @Captor private ArgumentCaptor<GrpcGetRepresentationsResponse> responseCaptor; - private GrpcGetRepresentationsRequest request = GrpcGetRepresentationsRequestTestFactory.create(); + private final GrpcGetRepresentationsRequest request = GrpcGetRepresentationsRequestTestFactory.create(); @Test void getRepresentationsShouldReturnNonEmptyGrpcResponse() { diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java index 014f2626f235ae0be3919bd5efe3f29dd25b110c..345938ebf543117636cbcf9e28306daf1a29737f 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java @@ -31,6 +31,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -41,6 +42,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import de.ozgcloud.vorgang.vorgang.EingangTestFactory; import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory; import de.ozgcloud.vorgang.vorgang.VorgangTestFactory; @@ -110,7 +112,7 @@ class FileServiceTest { } @Test - void shouldReturnId() throws Exception { + void shouldReturnId() { var id = service.uploadFileStream(ref, file, user, contentStream); assertThat(id).isEqualTo(IncomingFileTestFactory.ID); @@ -131,7 +133,7 @@ class FileServiceTest { @Nested class TestFindFilesMetaData { - private Collection<FileId> ids = Collections.singleton(OzgFileTestFactory.ID); + private final Collection<FileId> ids = Collections.singleton(OzgFileTestFactory.ID); @BeforeEach void mockFileMapper() { @@ -162,4 +164,46 @@ class FileServiceTest { verify(binaryFileRepository).deleteAllByVorgang(VorgangTestFactory.ID); } } + + @Nested + class TestGetAttachments { + + @Test + void shouldCallFindAttachments() { + service.getAttachments(Optional.of(VorgangTestFactory.ID), Optional.ofNullable(EingangTestFactory.ID)); + + verify(repository).findAttachments(Optional.of(VorgangTestFactory.ID), Optional.ofNullable(EingangTestFactory.ID)); + } + + @Test + void shouldReturnAttachmentsByVorgangIdAndEingangId() { + var attachment = OzgFileTestFactory.create(); + when(repository.findAttachments(any(), any())).thenReturn(List.of(attachment)); + + var result = service.getAttachments(Optional.of(VorgangTestFactory.ID), Optional.ofNullable(EingangTestFactory.ID)); + + assertThat(result).containsExactly(attachment); + } + } + + @Nested + class TestGetRepresentations { + + @Test + void shouldCallFindRepresentations() { + service.getRepresentations(Optional.of(VorgangTestFactory.ID), Optional.ofNullable(EingangTestFactory.ID)); + + verify(repository).findRepresentations(Optional.of(VorgangTestFactory.ID), Optional.ofNullable(EingangTestFactory.ID)); + } + + @Test + void shouldReturnRepresentationsByVorgangIdAndEingangId() { + var representation = OzgFileTestFactory.create(); + when(repository.findRepresentations(any(), any())).thenReturn(List.of(representation)); + + var result = service.getRepresentations(Optional.of(VorgangTestFactory.ID), Optional.ofNullable(EingangTestFactory.ID)); + + assertThat(result).containsExactly(representation); + } + } } \ No newline at end of file diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcFileServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcFileServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d4a0da11c1a296928eb79049b1c5e7023eecd256 --- /dev/null +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcFileServiceTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.vorgang.files; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsResponse; +import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsResponse; +import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile; +import io.grpc.stub.StreamObserver; + +class GrpcFileServiceTest { + + private static final GrpcOzgFile GRPC_OZG_FILE = GrpcOzgFileTestFactory.create(); + + @InjectMocks + private GrpcFileService grpcFileService; + + @Mock + private FileService fileService; + + @Mock + private GrpcOzgFileMapper fileMapper; + + @BeforeEach + void init() { + when(fileMapper.map(anyList())).thenReturn(List.of(GRPC_OZG_FILE)); + } + + @Nested + class TestGetAttachments { + + @Mock + private StreamObserver<GrpcGetAttachmentsResponse> responseObserver; + + @Captor + private ArgumentCaptor<GrpcGetAttachmentsResponse> responseCaptor; + + @Test + void shouldCallGetAttachments() { + getAttachments(); + + verify(fileService).getAttachments(Optional.ofNullable(GrpcGetAttachmentsRequestTestFactory.VORGANG_ID), + Optional.ofNullable(GrpcGetAttachmentsRequestTestFactory.EINGANG_ID)); + } + + @Test + void shouldCallFileMapper() { + var ozgFiles = List.of(OzgFileTestFactory.create()); + when(fileService.getAttachments(any(), any())).thenReturn(ozgFiles); + + getAttachments(); + + verify(fileMapper).map(ozgFiles); + } + + @Test + void shouldAddFilesToResponse() { + getAttachments(); + + verify(responseObserver).onNext(responseCaptor.capture()); + assertThat(responseCaptor.getValue().getFileList()).containsExactly(GRPC_OZG_FILE); + } + + @Test + void shouldCallCompleted() { + getAttachments(); + + verify(responseObserver).onCompleted(); + } + + private void getAttachments() { + grpcFileService.getAttachments(GrpcGetAttachmentsRequestTestFactory.create(), responseObserver); + } + } + + @Nested + class TestGetRepresentations { + + @Mock + private StreamObserver<GrpcGetRepresentationsResponse> responseObserver; + + @Captor + private ArgumentCaptor<GrpcGetRepresentationsResponse> responseCaptor; + + @Test + void shouldCallGetRepresentations() { + getRepresentations(); + + verify(fileService).getRepresentations(Optional.of(GrpcGetRepresentationsRequestTestFactory.VORGANG_ID), + Optional.of(GrpcGetRepresentationsRequestTestFactory.EINGANG_ID)); + } + + @Test + void shouldCallFileMapper() { + var ozgFiles = List.of(OzgFileTestFactory.create()); + when(fileService.getRepresentations(any(), any())).thenReturn(ozgFiles); + + getRepresentations(); + + verify(fileMapper).map(ozgFiles); + } + + @Test + void shouldAddFilesToResponse() { + getRepresentations(); + + verify(responseObserver).onNext(responseCaptor.capture()); + assertThat(responseCaptor.getValue().getFileList()).containsExactly(GRPC_OZG_FILE); + } + + @Test + void shouldCallCompleted() { + getRepresentations(); + + verify(responseObserver).onCompleted(); + } + + private void getRepresentations() { + grpcFileService.getRepresentations(GrpcGetRepresentationsRequestTestFactory.create(), responseObserver); + } + } +} \ No newline at end of file diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java index d33e4d90b6067d3872c824e2ebfa1a6b72e9da15..e19787b667a256e1ffd79c5e3cfbc519d4309725 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java @@ -25,9 +25,11 @@ package de.ozgcloud.vorgang.files; import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsRequest; import de.ozgcloud.vorgang.vorgang.EingangTestFactory; +import de.ozgcloud.vorgang.vorgang.VorgangTestFactory; public class GrpcGetAttachmentsRequestTestFactory { + public static final String VORGANG_ID = VorgangTestFactory.ID; public static final String EINGANG_ID = EingangTestFactory.ID; public static GrpcGetAttachmentsRequest create() { @@ -36,6 +38,7 @@ public class GrpcGetAttachmentsRequestTestFactory { public static GrpcGetAttachmentsRequest.Builder createBuilder() { return GrpcGetAttachmentsRequest.newBuilder() - .setEingangId(EINGANG_ID); + .setEingangId(EINGANG_ID) + .setVorgangId(VORGANG_ID); } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java index 55e5de3da4ca62bf1c9b4ed05dbd49f73683cc8a..7408b7bb7156096578840c28efa6dd26552ab7af 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java @@ -25,10 +25,12 @@ package de.ozgcloud.vorgang.files; import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsRequest; import de.ozgcloud.vorgang.vorgang.EingangTestFactory; +import de.ozgcloud.vorgang.vorgang.VorgangTestFactory; public class GrpcGetRepresentationsRequestTestFactory { public static final String EINGANG_ID = EingangTestFactory.ID; + public static final String VORGANG_ID = VorgangTestFactory.ID; public static GrpcGetRepresentationsRequest create() { return createBuilder().build(); @@ -36,6 +38,7 @@ public class GrpcGetRepresentationsRequestTestFactory { public static GrpcGetRepresentationsRequest.Builder createBuilder() { return GrpcGetRepresentationsRequest.newBuilder() - .setEingangId(EINGANG_ID); + .setEingangId(EINGANG_ID) + .setVorgangId(VORGANG_ID); } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcOzgFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcOzgFileTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e2dec587074c6fa5d6a13ef1be50e9bbddaa1bbd --- /dev/null +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcOzgFileTestFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.vorgang.files; + +import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile; + +public class GrpcOzgFileTestFactory { + + public static GrpcOzgFile create() { + return createBuilder().build(); + } + + public static GrpcOzgFile.Builder createBuilder() { + return GrpcOzgFile.newBuilder() + .setId(OzgFileTestFactory.ID.toString()) + .setName(OzgFileTestFactory.NAME) + .setSize(OzgFileTestFactory.SIZE) + .setContentType(OzgFileTestFactory.CONTENT_TYPE); + } +}