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 5a1517e9a38c2202fb65d56a700906f0e1ebcd0a..38f5f9ab65e9255882608362fdd2f938542c53a8 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 @@ -24,7 +24,6 @@ package de.ozgcloud.vorgang.files; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +33,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 @@ -42,36 +42,37 @@ 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 DB_FIELDNAME_EINGANG_ID = DB_FIELDNAME_EINGANGS + "._id"; private static final String DB_FIELDNAME_FILES = "files"; - private static final String FIELD_ATTACHMENT_FILES = DB_FIELDNAME_EINGANGS + "." + DB_FIELDNAME_ATTACHMENTS + "." + DB_FIELDNAME_FILES; - - private static final String DB_FIELDNAME_REPRESENTATIONS = "representations"; - private static final String FIELD_REPRESENTATION_FILES = DB_FIELDNAME_EINGANGS + "." + DB_FIELDNAME_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"; public List<OzgFile> findAttachmentsByEingangId(String eingangId) { - - List<AggregationOperation> operations = new ArrayList<>(); - - operations.add(Aggregation.match(new Criteria(DB_FIELDNAME_EINGANG_ID).is(eingangId))); - operations.addAll(buildFindAttachmentsAggregation()); - - return mongoTemplate.aggregate(Aggregation.newAggregation(operations), Vorgang.COLLECTION_NAME, OzgFile.class).getMappedResults(); + return findAttachments(Criteria.where(DB_FIELDNAME_EINGANG_ID).is(eingangId)); } public List<OzgFile> findAttachmentsByVorgangId(String vorgangId) { - return Collections.emptyList(); + return findAttachments(CriteriaUtil.isId(vorgangId)); } public List<OzgFile> findAttachmentsByVorgangIdAndEingangId(final String vorgangId, final String eingangId) { - return Collections.emptyList(); + return findAttachments(new Criteria().andOperator(CriteriaUtil.isId(vorgangId), Criteria.where(DB_FIELDNAME_EINGANG_ID).is(eingangId))); } - private List<AggregationOperation> buildFindAttachmentsAggregation() { + private List<OzgFile> findAttachments(Criteria criteria) { + List<AggregationOperation> operations = new ArrayList<>(); + operations.add(Aggregation.match(criteria)); + operations.addAll(buildExtractAttachmentsAggregation()); + + return mongoTemplate.aggregate(Aggregation.newAggregation(operations), Vorgang.COLLECTION_NAME, OzgFile.class).getMappedResults(); + } + + private List<AggregationOperation> buildExtractAttachmentsAggregation() { return List.of( - Aggregation.project().andExpression(FIELD_ATTACHMENT_FILES).as(DB_FIELDNAME_FILES), + 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), @@ -80,27 +81,30 @@ class EingangFilesRepository { } List<OzgFile> findRepresentationsByEingangId(String eingangId) { - - List<AggregationOperation> operations = new ArrayList<>(); - - operations.add(Aggregation.match(new Criteria(DB_FIELDNAME_EINGANG_ID).is(eingangId))); - operations.addAll(buildFindRepresentationsAggregation()); - - return mongoTemplate.aggregate(Aggregation.newAggregation(operations), Vorgang.COLLECTION_NAME, OzgFile.class).getMappedResults(); + return findRepresentations(Criteria.where(DB_FIELDNAME_EINGANG_ID).is(eingangId)); } public List<OzgFile> findRepresentationsByVorgangId(String vorgangId) { - return Collections.emptyList(); + return findRepresentations(CriteriaUtil.isId(vorgangId)); } public List<OzgFile> findRepresentationsByVorgangIdAndEingangId(String vorgangId, String eingangId) { - return Collections.emptyList(); + return findRepresentations(new Criteria().andOperator(CriteriaUtil.isId(vorgangId), Criteria.where(DB_FIELDNAME_EINGANG_ID).is(eingangId))); } - private List<AggregationOperation> buildFindRepresentationsAggregation() { + private List<OzgFile> findRepresentations(Criteria criteria) { + List<AggregationOperation> operations = new ArrayList<>(); + operations.add(Aggregation.match(criteria)); + operations.addAll(buildFindRepresentationsAggregation()); + + return mongoTemplate.aggregate(Aggregation.newAggregation(operations), Vorgang.COLLECTION_NAME, OzgFile.class).getMappedResults(); + } + private List<AggregationOperation> buildFindRepresentationsAggregation() { return List.of( 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)); 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..da17690713e1cef829f7ea8a9c40a209b50f5702 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,7 @@ package de.ozgcloud.vorgang.files; import static org.assertj.core.api.Assertions.*; import java.util.List; +import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -61,27 +62,99 @@ 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 = repository.findAttachmentsByEingangId(EingangTestFactory.ID); + + assertThat(attachments).hasSize(2); + } + + @Test + void validateFirstAttachment() { + OzgFile attachment = repository.findAttachmentsByEingangId(EingangTestFactory.ID).get(0); + + assertThat(attachment.getId()).isEqualTo(IncomingFileTestFactory.ID); + assertThat(attachment.getName()).isEqualTo(IncomingFileTestFactory.NAME); + assertThat(attachment.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + } + + @Test + void validateSecondAttachment() { + OzgFile attachment = repository.findAttachmentsByEingangId(EingangTestFactory.ID).get(1); + + assertThat(attachment.getId()).isEqualTo(ID2); + } } - @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 = repository.findAttachmentsByVorgangId(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 = repository.findAttachmentsByVorgangId(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 = repository.findAttachmentsByVorgangId(vorgang.getId()); + + assertThat(result).isEmpty(); + } } - @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.findAttachmentsByVorgangIdAndEingangId(vorgang.getId(), "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.findAttachmentsByVorgangIdAndEingangId(vorgang.getId(), eingangId); - assertThat(attachment.getId()).isEqualTo(ID2); + assertThat(result).hasSize(3); + } } } @@ -96,29 +169,98 @@ 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 = repository.findRepresentationsByEingangId(EingangTestFactory.ID); + + assertThat(representations).hasSize(2); + } + + @Test + void validateFirstRepresentation() { + OzgFile representation = repository.findRepresentationsByEingangId(EingangTestFactory.ID).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 = repository.findRepresentationsByEingangId(EingangTestFactory.ID).get(1); + + assertThat(representation.getId()).isEqualTo(ID2); + assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); + assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + } } - @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 = repository.findRepresentationsByVorgangId(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 = repository.findRepresentationsByVorgangId(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 = repository.findRepresentationsByVorgangId(vorgang.getId()); + + assertThat(result).isEmpty(); + } } - @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.findAttachmentsByVorgangIdAndEingangId(vorgang.getId(), "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.findRepresentationsByVorgangIdAndEingangId(vorgang.getId(), eingangId); - assertThat(representation.getId()).isEqualTo(ID2); - assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); - assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); + assertThat(result).hasSize(2); + } } }