From 6c95fb6e88711af55d67c7dd03f8472002b22ee5 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Wed, 12 Mar 2025 14:32:36 +0100 Subject: [PATCH 01/28] OZG-7573 OZG-7925 expand Mapping from GrpcEignang to FormData --- .../formdata/AntragstellerTestFactory.java | 7 +- .../common/formdata/FormDataTestFactory.java | 15 +-- .../formdata/PostfachAddressTestFactory.java | 4 +- .../ZustaendigeStelleTestFactory.java | 4 + .../eingang/router/GrpcEingangMapper.java | 18 +-- .../eingang/router/ServiceKontoMapper.java | 64 +++++----- .../router/GrpcAntragstellerTestFactory.java | 81 +++++++++++++ .../router/GrpcEingangHeaderTestFactory.java | 4 +- .../eingang/router/GrpcEingangMapperTest.java | 110 ++++++++++++++---- .../router/GrpcEingangTestFactory.java | 57 +++++++++ .../GrpcIncomingFileGroupTestFactory.java | 3 +- .../router/GrpcIncomingFileTestFactory.java | 2 +- .../GrpcPostfachAddressTestFactory.java | 33 ++++++ .../router/GrpcServiceKontoTestFactory.java | 25 ++++ .../GrpcZustaendigeStelleTestFactory.java | 57 +++++++++ .../router/ServiceKontoMapperTest.java | 44 ++++++- 16 files changed, 450 insertions(+), 78 deletions(-) create mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java create mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java create mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java create mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java create mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/AntragstellerTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/AntragstellerTestFactory.java index 4418a4fc7..acb3f7384 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/AntragstellerTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/AntragstellerTestFactory.java @@ -38,6 +38,9 @@ public class AntragstellerTestFactory { public static final String SUB_VERBOTENE_VEREINIGUNG_KEY = "MitgliedschaftInVerboternerVereinigung"; public static final String SUB_VERBOTENE_VEREINIGUNG_VALUE = "true"; + public static final Map<String, Object> DATA = Map.of(GEBIET_BEZEICHNUNG_KEY, GEBIET_BEZEICHNUNG_VALUE, + SUB_PERSOENLICHE_EIGNUNG, Map.of(SUB_VERBOTENE_VEREINIGUNG_KEY, SUB_VERBOTENE_VEREINIGUNG_VALUE)); + public static final String VORNAME = "Theo"; public static final String NACHNAME = "Test"; public static final String GEBURTSNAME = "Toast"; @@ -82,8 +85,6 @@ public class AntragstellerTestFactory { .plz(PLZ) .ort(ORT) .postfachId(POSTFACH_ID) - .data(Map.of(GEBIET_BEZEICHNUNG_KEY, GEBIET_BEZEICHNUNG_VALUE, - SUB_PERSOENLICHE_EIGNUNG, - Map.of(SUB_VERBOTENE_VEREINIGUNG_KEY, SUB_VERBOTENE_VEREINIGUNG_VALUE))); + .data(DATA); } } diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java index 1c5ceaddf..94f756da0 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import de.ozgcloud.eingang.common.formdata.FormData.FormDataControl; import lombok.AccessLevel; @@ -36,6 +37,7 @@ import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class FormDataTestFactory { + public static final String ID = UUID.randomUUID().toString(); public static final String SIMPLE_VALUE_KEY = "kontaktsystemtypid"; public static final String SIMPLE_VALUE = "233034600"; @@ -54,12 +56,9 @@ public class FormDataTestFactory { public static final Map<String, Object> NESTED_LIST_OBJECTS_ELEMENT_2 = Map.of("o3", "o4"); public static final List<Map<String, Object>> NESTED_LIST_WITH_OBJECTS = List.of(NESTED_LIST_OBJECTS_ELEMENT_1, NESTED_LIST_OBJECTS_ELEMENT_2); - public static final String ATTACHMENT_GROUP_2 = "FileGroup2"; - public static final String VORGANG_ID = "vorgangId"; - public static final List<IncomingFileGroup> ATTACHMENTS = List.of(IncomingFileGroupTestFactory.create(), - IncomingFileGroupTestFactory.createBuilder().name(ATTACHMENT_GROUP_2).build()); + public static final List<IncomingFileGroup> ATTACHMENTS = List.of(IncomingFileGroupTestFactory.create()); public static final List<IncomingFile> REPRESENTATIONS = List.of(IncomingFileTestFactory.create()); public static final FormDataControl FORM_DATA_CONTROL = FormDataControlTestFactory.create(); @@ -76,17 +75,15 @@ public class FormDataTestFactory { public static FormData.FormDataBuilder createBuilder() { return FormData.builder() + .id(ID) .header(FormHeaderTestFactory.create()) .antragsteller(AntragstellerTestFactory.create()) .zustaendigeStelle(ZustaendigeStelleTestFactory.create()) .control(FORM_DATA_CONTROL) .formData(FORM_DATA) - // TODO nach entfernen des zweiten Attachments den Wert auf 1 setzen - .numberOfAttachments(2) - // TODO zweites Attachment aus der TestFactory entfernen und die entsprechenden - // Tests anpassen + .numberOfAttachments(ATTACHMENTS.size()) .attachments(ATTACHMENTS) - .numberOfRepresentations(1) + .numberOfRepresentations(REPRESENTATIONS.size()) .representations(REPRESENTATIONS); } diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/PostfachAddressTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/PostfachAddressTestFactory.java index 0e3e2a281..a7d2fa3ce 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/PostfachAddressTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/PostfachAddressTestFactory.java @@ -25,11 +25,13 @@ package de.ozgcloud.eingang.common.formdata; import java.util.UUID; +import org.apache.commons.lang3.RandomUtils; + import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress; public class PostfachAddressTestFactory { - public static final int POSTFACH_ADDRESS_TYPE = 1; + public static final int POSTFACH_ADDRESS_TYPE = RandomUtils.insecure().randomInt(); public static final String VERSION = "1.0"; public static final String POSTFACH_ID = UUID.randomUUID().toString(); diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/ZustaendigeStelleTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/ZustaendigeStelleTestFactory.java index 5b14fe2d5..34adca8f0 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/ZustaendigeStelleTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/ZustaendigeStelleTestFactory.java @@ -23,6 +23,8 @@ */ package de.ozgcloud.eingang.common.formdata; +import com.thedeanda.lorem.LoremIpsum; + public class ZustaendigeStelleTestFactory { public static final String ORGANISATIONSEINHEIT_ID = "08150815"; @@ -33,6 +35,7 @@ public class ZustaendigeStelleTestFactory { public static final String HAUSANSCHRIFT_PLZ = "12345"; public static final String HAUSANSCHRIFT_ORT = "Musterort"; public static final String TELEFON = "0123456789"; + public static final String BEZEICHNUNG = LoremIpsum.getInstance().getWords(5); public static ZustaendigeStelle create() { return createBuilder().build(); @@ -42,6 +45,7 @@ public class ZustaendigeStelleTestFactory { return ZustaendigeStelle.builder() // .organisationseinheitenId(ORGANISATIONSEINHEIT_ID) .email(EMAIL) + .bezeichnung(BEZEICHNUNG) .gemeindeSchluessel(GEMEINDE_SCHLUESSEL) .amtlicherRegionalSchluessel(AMTLICHER_REGIONAL_SCHLUESSEL) .hausanschriftStrasse(HAUSANSCHRIFT_STRASSE) diff --git a/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java b/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java index eb5d7c414..382c59752 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java @@ -44,7 +44,6 @@ import de.ozgcloud.vorgang.vorgang.GrpcIncomingFileGroup; import de.ozgcloud.vorgang.vorgang.GrpcZustaendigeStelle; @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // - unmappedSourcePolicy = ReportingPolicy.WARN, // nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, // @@ -59,8 +58,8 @@ public interface GrpcEingangMapper { default ZustaendigeStelle getZustaendigeStelle(FormData formData, Optional<String> organisationsEinheitenId) { return organisationsEinheitenId.flatMap(oeId -> formData.getZustaendigeStelles().stream() - .filter(zustaendigeStelle -> zustaendigeStelle.getOrganisationseinheitenId().equals(oeId)) - .findFirst()) + .filter(zustaendigeStelle -> zustaendigeStelle.getOrganisationseinheitenId().equals(oeId)) + .findFirst()) .orElseGet(() -> ZustaendigeStelle.builder().build()); } @@ -84,13 +83,16 @@ public interface GrpcEingangMapper { return id.toString(); } - // FIXME map representations and attachments @Mapping(target = "attachment", ignore = true) - @Mapping(target = "attachments", ignore = true) @Mapping(target = "representation", ignore = true) - @Mapping(target = "representations", ignore = true) - // TOASK: Wird aktuell nicht gebraucht, trotzdem implementiern? - @Mapping(target = "header.serviceKonto", ignore = true) + @Mapping(target = "zustaendigeStelles", ignore = true) + @Mapping(target = "control", ignore = true) + @Mapping(target = "attachments", source = "attachmentsList") + @Mapping(target = "representations", source = "representationsList") + @Mapping(target = "antragsteller.data", source = "antragsteller.otherData") FormData toFormData(GrpcEingang eingang); + @Mapping(target = "files", source = "filesList") + @Mapping(target = "file", ignore = true) + IncomingFileGroup mapFileGroupFromGrpc(GrpcIncomingFileGroup fileGroup); } diff --git a/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java b/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java index 7986140e7..85b8a1685 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java @@ -23,55 +23,67 @@ */ package de.ozgcloud.eingang.router; -import java.util.List; import java.util.Map; -import java.util.Optional; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.ReportingPolicy; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import de.ozgcloud.eingang.common.formdata.PostfachAddressIdentifier; import de.ozgcloud.eingang.common.formdata.ServiceKonto; import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier; -import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress; import de.ozgcloud.vorgang.common.GrpcObject; import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper; -import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress; import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; -@Component -class ServiceKontoMapper { +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, // + uses = { GrpcObjectMapper.class }) +abstract class ServiceKontoMapper { static final String DEFAULT_TRUST_LEVEL = "STORK-QAA-Level-1"; @Autowired private GrpcObjectMapper grpcObjectMapper; - public GrpcServiceKonto toServiceKonto(ServiceKonto serviceKonto) { - return GrpcServiceKonto.newBuilder() - .setType(serviceKonto.getType()) - .addAllPostfachAddresses(getPostfachAddresses(serviceKonto)) - .setTrustLevel(Optional.ofNullable(serviceKonto.getTrustLevel()).orElse(DEFAULT_TRUST_LEVEL)) - .build(); - } + @Mapping(target = "postfachAddressesList", source = "postfachAddresses") + @Mapping(target = "trustLevel", source = "trustLevel", defaultValue = DEFAULT_TRUST_LEVEL) + abstract GrpcServiceKonto toGrpc(ServiceKonto serviceKonto); - private List<GrpcPostfachAddress> getPostfachAddresses(ServiceKonto serviceKonto) { - return serviceKonto.getPostfachAddresses().stream().map(this::fromPostfachAddress).toList(); + GrpcObject mapFromIdentifier(PostfachAddressIdentifier identifier) { + return grpcObjectMapper.fromMap(Map.of(StringBasedIdentifier.POSTFACH_ID_FIELD, + getStringBasedValue(identifier))); } - private GrpcPostfachAddress fromPostfachAddress(PostfachAddress postfachAddress) { - return GrpcPostfachAddress.newBuilder() - .setVersion(postfachAddress.getVersion()) - .setType(postfachAddress.getType()) - .setIdentifier(mapFromIdentifier(postfachAddress.getIdentifier())) - .build(); + String getStringBasedValue(PostfachAddressIdentifier identifier) { + return ((StringBasedIdentifier) identifier).getPostfachId(); } - GrpcObject mapFromIdentifier(PostfachAddressIdentifier identifier) { - return grpcObjectMapper.fromMap(Map.of(StringBasedIdentifier.POSTFACH_ID_FIELD, getStringBasedValue(identifier))); + @Mapping(target = "postfachAddresses", source = "postfachAddressesList") + @Mapping(target = "trustLevel", source = "trustLevel", qualifiedByName = "mapTrustLevel") + @Mapping(target = "postfachAddress", ignore = true) + abstract ServiceKonto fromGrpc(GrpcServiceKonto serviceKonto); + + PostfachAddressIdentifier mapToIdentifier(GrpcObject identifier) { + var stringIdentifier = MapUtils.getString(grpcObjectMapper.mapFromGrpc(identifier), StringBasedIdentifier.POSTFACH_ID_FIELD); + return StringBasedIdentifier.builder().postfachId(stringIdentifier).build(); } - private String getStringBasedValue(PostfachAddressIdentifier identifier) { - return ((StringBasedIdentifier) identifier).getPostfachId(); + @Named("mapTrustLevel") + String mapTrustLevel(String trustLevel) { + if (StringUtils.isEmpty(trustLevel)) { + return DEFAULT_TRUST_LEVEL; + } + return trustLevel; } + } \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java new file mode 100644 index 000000000..61893f6a7 --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2025 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.eingang.router; + +import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; +import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; +import de.ozgcloud.vorgang.vorgang.GrpcFormData; +import de.ozgcloud.vorgang.vorgang.GrpcFormField; +import de.ozgcloud.vorgang.vorgang.GrpcSubForm; + +public class GrpcAntragstellerTestFactory { + + public static final String ANREDE = AntragstellerTestFactory.ANREDE; + public static final String NACHNAME = AntragstellerTestFactory.NACHNAME; + public static final String VORNAME = AntragstellerTestFactory.VORNAME; + public static final String GEBURTSDATUM = AntragstellerTestFactory.GEBURTSDATUM; + public static final String GEBURTSORT = AntragstellerTestFactory.GEBURTSORT; + public static final String GEBURTSNAME = AntragstellerTestFactory.GEBURTSNAME; + public static final String EMAIL = AntragstellerTestFactory.EMAIL; + public static final String TELEFON = AntragstellerTestFactory.TELEFON; + public static final String STRASSE = AntragstellerTestFactory.STRASSE; + public static final String HAUSNUMMER = AntragstellerTestFactory.HAUSNUMMER; + public static final String PLZ = AntragstellerTestFactory.PLZ; + public static final String ORT = AntragstellerTestFactory.ORT; + + public static final String POSTFACH_ID = AntragstellerTestFactory.POSTFACH_ID; + public static final GrpcFormData OTHER_DATA = GrpcFormData.newBuilder() + .addField(GrpcFormField.newBuilder() + .setName(AntragstellerTestFactory.GEBIET_BEZEICHNUNG_KEY) + .setValue(AntragstellerTestFactory.GEBIET_BEZEICHNUNG_VALUE).build()) + .addForm(GrpcSubForm.newBuilder().setTitle(AntragstellerTestFactory.SUB_PERSOENLICHE_EIGNUNG) + .addField(GrpcFormField.newBuilder() + .setName(AntragstellerTestFactory.SUB_VERBOTENE_VEREINIGUNG_KEY) + .setValue(AntragstellerTestFactory.SUB_VERBOTENE_VEREINIGUNG_VALUE).build()) + .build()) + .build(); + + public static GrpcAntragsteller create() { + return createBuilder().build(); + } + + public static GrpcAntragsteller.Builder createBuilder() { + return GrpcAntragsteller.newBuilder() + .setAnrede(ANREDE) + .setFirmaName(AntragstellerTestFactory.FIRMA_NAME) + .setGeburtsdatum(GEBURTSDATUM) + .setNachname(NACHNAME) + .setVorname(VORNAME) + .setGeburtsname(GEBURTSNAME) + .setGeburtsort(GEBURTSORT) + .setEmail(EMAIL) + .setTelefon(TELEFON) + .setStrasse(STRASSE) + .setHausnummer(HAUSNUMMER) + .setPlz(PLZ) + .setOrt(ORT) + .setPostfachId(POSTFACH_ID) + .setOtherData(OTHER_DATA); + } +} \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangHeaderTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangHeaderTestFactory.java index e7fbc2a6d..1c2f14b48 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangHeaderTestFactory.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangHeaderTestFactory.java @@ -30,6 +30,8 @@ import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; public class GrpcEingangHeaderTestFactory { + public static final GrpcServiceKonto SERVICE_KONTO = GrpcServiceKontoTestFactory.create(); + public static GrpcEingangHeader create() { return createBuilder().build(); } @@ -42,7 +44,7 @@ public class GrpcEingangHeaderTestFactory { .setFormEngineName(FORM_ENGINE_NAME) .setFormName(FORM_NAME) .setSender(SENDER) - .setServiceKonto(GrpcServiceKonto.newBuilder().build()) + .setServiceKonto(SERVICE_KONTO) .setVorgangNummer(VORGANG_NUMMER); } } diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java index 15ee7c6b7..a262e8c7a 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java @@ -40,12 +40,12 @@ import org.mockito.Mock; import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelleTestFactory; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper; import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; import de.ozgcloud.vorgang.vorgang.GrpcEingang; import de.ozgcloud.vorgang.vorgang.GrpcFormData; -import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; import de.ozgcloud.vorgang.vorgang.GrpcZustaendigeStelle; class GrpcEingangMapperTest { @@ -109,7 +109,7 @@ class GrpcEingangMapperTest { void mockMapperReturnValues() { when(grpcFormDataMapper.mapToFormData(anyMap())) .thenReturn(GrpcFormData.newBuilder().addField(GrpcFormFieldTestFactory.create()).build()); - when(serviceKontoMapper.toServiceKonto(any())).thenReturn(GrpcServiceKonto.newBuilder().build()); + when(serviceKontoMapper.toGrpc(any())).thenReturn(GrpcServiceKontoTestFactory.create()); } @Nested @@ -134,14 +134,14 @@ class GrpcEingangMapperTest { void validateNumberOfAttachments() { var eingang = toEingang(); - assertThat(eingang.getNumberOfAttachments()).isEqualTo(2); + assertThat(eingang.getNumberOfAttachments()).isEqualTo(FormDataTestFactory.ATTACHMENTS.size()); } @Test void validateNumberOfAttachmentGroups() { var eingang = toEingang(); - assertThat(eingang.getAttachmentsCount()).isEqualTo(2); + assertThat(eingang.getAttachmentsCount()).isEqualTo(FormDataTestFactory.ATTACHMENTS.size()); } @Test @@ -162,25 +162,6 @@ class GrpcEingangMapperTest { assertThat(attachment.getContentType()).isEqualTo(IncomingFileTestFactory.CONTENT_TYPE); assertThat(attachment.getContent()).isEmpty(); } - - @Test - void validateGroup2AttachmentCount() { - var eingang = toEingang(); - - assertThat(eingang.getAttachmentsList().get(1).getFilesCount()).isEqualTo(1); - } - - @Test - void validateGroup2Attachment() { - var eingang = toEingang(); - - var attachment = eingang.getAttachmentsList().get(1).getFilesList().get(0); - assertThat(attachment.getId()).isEqualTo(IncomingFileTestFactory.ID); - assertThat(attachment.getVendorId()).isEqualTo(IncomingFileTestFactory.VENDOR_ID); - assertThat(attachment.getName()).isEqualTo(IncomingFileTestFactory.NAME); - assertThat(attachment.getContentType()).isEqualTo(IncomingFileTestFactory.CONTENT_TYPE); - assertThat(attachment.getContent()).isEmpty(); - } } @Nested @@ -217,4 +198,87 @@ class GrpcEingangMapperTest { return mapper.toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)); } } + + @Nested + class TestToFormData { + + private final GrpcEingang eingang = GrpcEingangTestFactory.create(); + + @BeforeEach + void mock() { + when(serviceKontoMapper.fromGrpc(any())).thenReturn(ServiceKontoTestFactory.create()); + when(grpcFormDataMapper.mapFromFormData(GrpcAntragstellerTestFactory.OTHER_DATA)).thenReturn(AntragstellerTestFactory.DATA); + when(grpcFormDataMapper.mapFromFormData(GrpcEingangTestFactory.FORM_DATA)).thenReturn(FormDataTestFactory.FORM_DATA); + } + + @Test + void shouldCallServiceKontoMapper() { + mapper.toFormData(eingang); + + verify(serviceKontoMapper).fromGrpc(GrpcEingangHeaderTestFactory.SERVICE_KONTO); + } + + @Test + void shouldCallFormDataMapperWithAntragstellerData() { + mapper.toFormData(eingang); + + verify(grpcFormDataMapper).mapFromFormData(GrpcAntragstellerTestFactory.OTHER_DATA); + } + + @Test + void shouldCallFormDataMapperWithFormData() { + mapper.toFormData(eingang); + + verify(grpcFormDataMapper).mapFromFormData(GrpcEingangTestFactory.FORM_DATA); + } + + @Test + void shouldMapToFormData() { + var expectedFormData = FormDataTestFactory.createBuilder() + .numberOfAttachments(GrpcEingangTestFactory.NUMBER_OF_ATTACHMENTS) + .numberOfRepresentations(GrpcEingangTestFactory.NUMBER_OF_REPRESENTATIONS) + .build(); + + var formData = mapper.toFormData(eingang); + + assertThat(formData).usingRecursiveComparison() + .ignoringFields("antragsteller.firmaName", "control", "attachments", "representations", "zustaendigeStelles") + .isEqualTo(expectedFormData); + } + + @Nested + class TestZustaendigestelles { + + @Test + void shouldMapZustaendigeStelles() { + var zustaendigeStelles = mapper.toFormData(eingang).getZustaendigeStelles(); + + assertThat(zustaendigeStelles).usingRecursiveFieldByFieldElementComparator().containsExactly(ZustaendigeStelleTestFactory.create()); + } + } + + @Nested + class TestAttachments { + + @Test + void shouldMapAttachments() { + var attachments = mapper.toFormData(eingang).getAttachments(); + + assertThat(attachments).usingRecursiveFieldByFieldElementComparatorIgnoringFields("files.file") + .containsExactly(FormDataTestFactory.ATTACHMENTS.get(0)); + } + } + + @Nested + class TestRepresentations { + + @Test + void shouldMapRepresentations() { + var representations = mapper.toFormData(eingang).getRepresentations(); + + assertThat(representations).usingRecursiveFieldByFieldElementComparatorIgnoringFields("file") + .containsExactly(FormDataTestFactory.REPRESENTATIONS.get(0)); + } + } + } } \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java new file mode 100644 index 000000000..8e15b541a --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 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.eingang.router; + +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory; +import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory; +import de.ozgcloud.vorgang.vorgang.GrpcEingang; +import de.ozgcloud.vorgang.vorgang.GrpcFormData; +import de.ozgcloud.vorgang.vorgang.GrpcSubForm; + +public class GrpcEingangTestFactory { + + public static final GrpcFormData FORM_DATA = GrpcFormDataTestFactory.create(); + public static final int NUMBER_OF_REPRESENTATIONS = 5; + public static final int NUMBER_OF_ATTACHMENTS = 4; + public static final String ID = FormDataTestFactory.ID; + public static final GrpcSubForm SUB_FORM = GrpcSubFormTestFactory.create(); + + public static GrpcEingang create() { + return createBuilder().build(); + } + + public static GrpcEingang.Builder createBuilder() { + return GrpcEingang.newBuilder() + .setId(ID) + .setHeader(GrpcEingangHeaderTestFactory.create()) + .setAntragsteller(GrpcAntragstellerTestFactory.create()) + .setZustaendigeStelle(GrpcZustaendigeStelleTestFactory.create()) + .setFormData(FORM_DATA) + .addAttachments(GrpcIncomingFileGroupTestFactory.create()) + .setNumberOfAttachments(NUMBER_OF_ATTACHMENTS) + .addRepresentations(GrpcIncomingFileTestFactory.create()) + .setNumberOfRepresentations(NUMBER_OF_REPRESENTATIONS); + } +} \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileGroupTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileGroupTestFactory.java index 8ffea9796..e8082ab91 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileGroupTestFactory.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileGroupTestFactory.java @@ -23,12 +23,13 @@ */ package de.ozgcloud.eingang.router; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.vorgang.vorgang.GrpcIncomingFile; import de.ozgcloud.vorgang.vorgang.GrpcIncomingFileGroup; public class GrpcIncomingFileGroupTestFactory { - public static final String NAME = "FileGroup1"; + public static final String NAME = IncomingFileGroupTestFactory.NAME; public static final GrpcIncomingFile FILE = GrpcIncomingFileTestFactory.create(); public static GrpcIncomingFileGroup create() { diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileTestFactory.java index dc5899c75..f72d588d6 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileTestFactory.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcIncomingFileTestFactory.java @@ -30,7 +30,7 @@ import de.ozgcloud.vorgang.vorgang.GrpcIncomingFile; public class GrpcIncomingFileTestFactory { - public static final String ID = IncomingFileTestFactory.ID.toString(); + public static final String ID = IncomingFileTestFactory.ID; public static final String VENDOR_ID = IncomingFileTestFactory.VENDOR_ID; public static final String NAME = IncomingFileTestFactory.NAME; public static final String CONTENT_TYPE = IncomingFileTestFactory.CONTENT_TYPE; diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java new file mode 100644 index 000000000..f8ba6cd4b --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java @@ -0,0 +1,33 @@ +package de.ozgcloud.eingang.router; + +import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; +import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier; +import de.ozgcloud.vorgang.common.GrpcObject; +import de.ozgcloud.vorgang.common.GrpcProperty; +import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress; +import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress.Builder; + +public class GrpcPostfachAddressTestFactory { + + public static final String VERSION = PostfachAddressTestFactory.VERSION; + public static final int TYPE = PostfachAddressTestFactory.POSTFACH_ADDRESS_TYPE; + public static final GrpcProperty IDENTIFIER_PROPERTY = GrpcProperty.newBuilder() + .setName(StringBasedIdentifier.POSTFACH_ID_FIELD) + .addValue(PostfachAddressTestFactory.POSTFACH_ID) + .build(); + public static final GrpcObject IDENTIFIER = GrpcObject.newBuilder() + .addProperty(IDENTIFIER_PROPERTY) + .build(); + + public static GrpcPostfachAddress create() { + return createBuilder().build(); + } + + private static Builder createBuilder() { + return GrpcPostfachAddress.newBuilder() + .setVersion(VERSION) + .setType(TYPE) + .setIdentifier(IDENTIFIER); + } + +} diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java new file mode 100644 index 000000000..1995e8123 --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java @@ -0,0 +1,25 @@ +package de.ozgcloud.eingang.router; + +import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; +import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress; +import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; +import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto.Builder; + +public class GrpcServiceKontoTestFactory { + + public static final GrpcPostfachAddress POSTFACH_ADDRESS = GrpcPostfachAddressTestFactory.create(); + public static final String TRUST_LEVEL = ServiceKontoTestFactory.TRUST_LEVEL; + public static final String TYPE = ServiceKontoTestFactory.TYPE; + + public static GrpcServiceKonto create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcServiceKonto.newBuilder() + .setType(TYPE) + .setTrustLevel(TRUST_LEVEL) + .addPostfachAddresses(POSTFACH_ADDRESS); + } + +} diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java new file mode 100644 index 000000000..d96403837 --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023 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.eingang.router; + +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelleTestFactory; +import de.ozgcloud.vorgang.vorgang.GrpcZustaendigeStelle; + +public class GrpcZustaendigeStelleTestFactory { + + public static final String ORGANISATIONSEINHEIT_ID = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID; + public static final String EMAIL = ZustaendigeStelleTestFactory.EMAIL; + public static final String GEMEINDE_SCHLUESSEL = ZustaendigeStelleTestFactory.GEMEINDE_SCHLUESSEL; + public static final String AMTLICHER_REGIONAL_SCHLUESSEL = ZustaendigeStelleTestFactory.AMTLICHER_REGIONAL_SCHLUESSEL; + public static final String HAUSANSCHRIFT_STRASSE = ZustaendigeStelleTestFactory.HAUSANSCHRIFT_STRASSE; + public static final String HAUSANSCHRIFT_PLZ = ZustaendigeStelleTestFactory.HAUSANSCHRIFT_PLZ; + public static final String HAUSANSCHRIFT_ORT = ZustaendigeStelleTestFactory.HAUSANSCHRIFT_ORT; + public static final String TELEFON = ZustaendigeStelleTestFactory.TELEFON; + public static final String BEZEICHNUNG = ZustaendigeStelleTestFactory.BEZEICHNUNG; + + public static GrpcZustaendigeStelle create() { + return createBuilder().build(); + } + + public static GrpcZustaendigeStelle.Builder createBuilder() { + return GrpcZustaendigeStelle.newBuilder() + .setOrganisationseinheitenId(ORGANISATIONSEINHEIT_ID) + .setEmail(EMAIL) + .setBezeichnung(BEZEICHNUNG) + .setGemeindeSchluessel(GEMEINDE_SCHLUESSEL) + .setAmtlicherRegionalSchluessel(AMTLICHER_REGIONAL_SCHLUESSEL) + .setHausanschriftStrasse(HAUSANSCHRIFT_STRASSE) + .setHausanschriftPlz(HAUSANSCHRIFT_PLZ) + .setHausanschriftOrt(HAUSANSCHRIFT_ORT) + .setTelefon(TELEFON); + } +} \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/ServiceKontoMapperTest.java b/router/src/test/java/de/ozgcloud/eingang/router/ServiceKontoMapperTest.java index 34cc0776f..f6389906f 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/ServiceKontoMapperTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/ServiceKontoMapperTest.java @@ -27,10 +27,14 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -45,13 +49,12 @@ import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; class ServiceKontoMapperTest { @InjectMocks - private ServiceKontoMapper mapper; + private final ServiceKontoMapper mapper = Mappers.getMapper(ServiceKontoMapper.class); @Mock private GrpcObjectMapper grpcObjectMapper; @Nested - @DisplayName("To servicekonto") - class TestMapServiceKonto { + class TestToGrpc { private final GrpcProperty grpcProperty = GrpcProperty.newBuilder() .setName(StringBasedIdentifier.POSTFACH_ID_FIELD) @@ -89,7 +92,7 @@ class ServiceKontoMapperTest { @Test void shouldContainsDefaultTrustLevel() { - var serviceKonto = mapper.toServiceKonto(ServiceKontoTestFactory.createBuilder().trustLevel(null).build()); + var serviceKonto = mapper.toGrpc(ServiceKontoTestFactory.createBuilder().trustLevel(null).build()); assertThat(serviceKonto.getTrustLevel()).isEqualTo(ServiceKontoMapper.DEFAULT_TRUST_LEVEL); } @@ -139,7 +142,38 @@ class ServiceKontoMapperTest { } private GrpcServiceKonto getServiceKontoFromMappedEingang() { - return mapper.toServiceKonto(ServiceKontoTestFactory.create()); + return mapper.toGrpc(ServiceKontoTestFactory.create()); + } + } + + @Nested + class TestFromGrpc { + + @BeforeEach + void mockGrpcObjectMapper() { + when(grpcObjectMapper.mapFromGrpc(any())) + .thenReturn(Map.of(StringBasedIdentifier.POSTFACH_ID_FIELD, PostfachAddressTestFactory.POSTFACH_ID)); + } + + @Test + void shouldCallGrpcMapper() { + mapper.fromGrpc(GrpcServiceKontoTestFactory.create()); + + verify(grpcObjectMapper).mapFromGrpc(GrpcPostfachAddressTestFactory.IDENTIFIER); + } + + @Test + void shouldMapToGrpc() { + var serviceKonto = mapper.fromGrpc(GrpcServiceKontoTestFactory.create()); + + assertThat(serviceKonto).usingRecursiveComparison().isEqualTo(ServiceKontoTestFactory.create()); + } + + @Test + void shouldSetDefaultTrustLevel() { + var serviceKonto = mapper.fromGrpc(GrpcServiceKontoTestFactory.createBuilder().setTrustLevel(StringUtils.EMPTY).build()); + + assertThat(serviceKonto.getTrustLevel()).isEqualTo(ServiceKontoMapper.DEFAULT_TRUST_LEVEL); } } } \ No newline at end of file -- GitLab From 7dfb7f91b04233409c442a65ec801a46ca0a4302 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Wed, 12 Mar 2025 14:47:41 +0100 Subject: [PATCH 02/28] OZG-7573 OZG-7929 forwarding call VorgangService --- forwarder/pom.xml | 6 ++ .../eingang/forwarder/RouteCriteria.java | 2 +- .../forwarder/RouteCriteriaMapper.java | 2 + .../forwarder/RouteForwardingGrpcService.java | 13 ++-- .../forwarder/RouteForwardingService.java | 14 +++- .../forwarder/RouteCriteriaTestFactory.java | 6 +- .../forwarder/RouteForwardingServiceTest.java | 66 +++++++++++++++++++ 7 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java diff --git a/forwarder/pom.xml b/forwarder/pom.xml index 8e11aac68..c09443335 100644 --- a/forwarder/pom.xml +++ b/forwarder/pom.xml @@ -86,6 +86,12 @@ <artifactId>lombok</artifactId> </dependency> + <!-- Test --> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>common</artifactId> + <type>test-jar</type> + </dependency> </dependencies> <build> diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java index b52e416dd..3a36486c9 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java @@ -34,5 +34,5 @@ public class RouteCriteria { private Optional<String> gemeindeSchluessel; private Optional<String> webserviceUrl; - private Optional<String> organisationseinheitenId; + private Optional<String> organisationEinheitId; } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java index d82fbd76b..7fcb6cea6 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java @@ -27,12 +27,14 @@ import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; @Mapper interface RouteCriteriaMapper { + @Mapping(target = "organisationEinheitId", source = "organisationseinheitenId") RouteCriteria fromGrpc(GrpcRouteCriteria grpcRouteCriteria); default Optional<String> wrapWithOptional(String val) { diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java index fa9c9d99a..6827f8839 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java @@ -23,24 +23,21 @@ */ package de.ozgcloud.eingang.forwarder; -import org.springframework.beans.factory.annotation.Autowired; - import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; import de.ozgcloud.eingang.router.GrpcEingangMapper; import io.grpc.stub.StreamObserver; +import lombok.RequiredArgsConstructor; import net.devh.boot.grpc.server.service.GrpcService; @GrpcService +@RequiredArgsConstructor public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.RouteForwardingServiceImplBase { - @Autowired - private RouteForwardingService service; - @Autowired - private RouteCriteriaMapper criteriaMapper; + private final RouteForwardingService service; + private final RouteCriteriaMapper criteriaMapper; - @Autowired - private GrpcEingangMapper eingangMapper; + private final GrpcEingangMapper eingangMapper; @Override public void routeForwarding(GrpcRouteForwardingRequest request, StreamObserver<GrpcRouteForwardingResponse> responseObserver) { diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java index 0079be1be..8df1ca5ae 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java @@ -26,11 +26,23 @@ package de.ozgcloud.eingang.forwarder; import org.springframework.stereotype.Service; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import de.ozgcloud.eingang.router.VorgangService; +import lombok.RequiredArgsConstructor; @Service +@RequiredArgsConstructor class RouteForwardingService { + private final VorgangService vorgangService; + public void route(RouteCriteria criteria, FormData formData) { -//FIXME implement me + vorgangService.createVorgang(formData.toBuilder() + .clearZustaendigeStelles() + .zustaendigeStelle(ZustaendigeStelle.builder() + .organisationseinheitenId(criteria.getOrganisationEinheitId() + .orElseThrow(() -> new UnsupportedOperationException("OrganisationseinheitId is required!"))) + .build()) + .build()); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java index f5b8c2742..82a9dc490 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java @@ -31,7 +31,7 @@ public class RouteCriteriaTestFactory { public static final String GEMEINDE_SCHLUSSEL = "0815"; public static final String WEBSERVICE_URL = "http://nimmerland.by.kop-cloud.de/ws"; - public static final String ORGANISATIONSEINHEITEN_ID = "4711"; + public static final String ORGANISATION_EINHEIT_ID = "4711"; public static RouteCriteria create() { return createBuilder().build(); @@ -41,7 +41,7 @@ public class RouteCriteriaTestFactory { return RouteCriteria.builder() .gemeindeSchluessel(Optional.of(GEMEINDE_SCHLUSSEL)) .webserviceUrl(Optional.of(WEBSERVICE_URL)) - .organisationseinheitenId(Optional.of(ORGANISATIONSEINHEITEN_ID)); + .organisationEinheitId(Optional.of(ORGANISATION_EINHEIT_ID)); } public static GrpcRouteCriteria createGrpc() { @@ -52,6 +52,6 @@ public class RouteCriteriaTestFactory { return GrpcRouteCriteria.newBuilder() .setGemeindeSchluessel(GEMEINDE_SCHLUSSEL) .setWebserviceUrl(WEBSERVICE_URL) - .setOrganisationseinheitenId(ORGANISATIONSEINHEITEN_ID); + .setOrganisationseinheitenId(ORGANISATION_EINHEIT_ID); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java new file mode 100644 index 000000000..e4c711fbc --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java @@ -0,0 +1,66 @@ +package de.ozgcloud.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Optional; + +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.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import de.ozgcloud.eingang.router.VorgangService; + +class RouteForwardingServiceTest { + + @InjectMocks + private RouteForwardingService routeForwardingService; + @Mock + private VorgangService vorgangService; + @Captor + private ArgumentCaptor<FormData> formDataCaptor; + + @Nested + class TestRoute { + + private final FormData formData = FormDataTestFactory.create(); + + @Test + void shouldCallVorgangService() { + var criteria = RouteCriteriaTestFactory.create(); + + routeForwardingService.route(criteria, formData); + + verify(vorgangService).createVorgang(formDataCaptor.capture()); + assertThat(formDataCaptor.getValue()).usingRecursiveComparison().ignoringFields("zustaendigeStelles").isEqualTo(formData); + } + + @Test + void shouldSetOrganisationEinheitIdInFormData() { + var criteria = RouteCriteriaTestFactory.create(); + var expectedZustaendigeStelle = ZustaendigeStelle.builder() + .organisationseinheitenId(RouteCriteriaTestFactory.ORGANISATION_EINHEIT_ID) + .build(); + + routeForwardingService.route(criteria, formData); + + verify(vorgangService).createVorgang(formDataCaptor.capture()); + assertThat(formDataCaptor.getValue().getZustaendigeStelles()).usingRecursiveFieldByFieldElementComparator() + .containsExactly(expectedZustaendigeStelle); + } + + @Test + void shouldThrowUnsupportedOperationException() { + var criteria = RouteCriteriaTestFactory.createBuilder().organisationEinheitId(Optional.empty()).build(); + + assertThrows(UnsupportedOperationException.class, () -> routeForwardingService.route(criteria, formData)); + } + } +} -- GitLab From 5be6f31452c5362b4d2ee84e1c287f1ddc9d5adb Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Wed, 12 Mar 2025 14:54:41 +0100 Subject: [PATCH 03/28] OZG-7573 fix unit test after test factory chagens --- .../de/ozgcloud/eingang/router/VorgangRemoteServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/src/test/java/de/ozgcloud/eingang/router/VorgangRemoteServiceTest.java b/router/src/test/java/de/ozgcloud/eingang/router/VorgangRemoteServiceTest.java index 7fda033b4..cc8cef24b 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/VorgangRemoteServiceTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/VorgangRemoteServiceTest.java @@ -342,7 +342,7 @@ class VorgangRemoteServiceTest { void shouldCallUploadIncomingFile() { vorgangCreator.uploadAttachments(); - verify(vorgangCreator, times(2)).uploadIncomingFile(any(IncomingFile.class)); + verify(vorgangCreator, times(FormDataTestFactory.ATTACHMENTS.size())).uploadIncomingFile(any(IncomingFile.class)); } @Test -- GitLab From c969cf801e006138d391bb0414218b46aa6842fd Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Wed, 12 Mar 2025 17:26:39 +0100 Subject: [PATCH 04/28] OZG-7573 more test fixing after test factory change --- forwarder/pom.xml | 13 ++++++ ...GrpcRouteForwardingRequestTestFactory.java | 9 +++- .../RouteForwardingGrpcServiceTest.java | 41 +++++++++--------- pom.xml | 7 ++++ router/pom.xml | 18 ++++++++ .../router/GrpcEingangMapperITCase.java | 42 ++++++++++++------- .../eingang/router/VorgangServiceTest.java | 4 +- 7 files changed, 96 insertions(+), 38 deletions(-) diff --git a/forwarder/pom.xml b/forwarder/pom.xml index c09443335..d79e4343e 100644 --- a/forwarder/pom.xml +++ b/forwarder/pom.xml @@ -91,6 +91,19 @@ <groupId>de.ozgcloud.eingang</groupId> <artifactId>common</artifactId> <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>router</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-utils</artifactId> + <type>test-jar</type> + <scope>test</scope> </dependency> </dependencies> diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java index 03c5beaed..37f758e1d 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java @@ -23,16 +23,23 @@ */ package de.ozgcloud.eingang.forwarder; +import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; +import de.ozgcloud.eingang.router.GrpcEingangTestFactory; +import de.ozgcloud.vorgang.vorgang.GrpcEingang; public class GrpcRouteForwardingRequestTestFactory { + public static final GrpcEingang EINGANG = GrpcEingangTestFactory.create(); + public static final GrpcRouteCriteria CRITERIA = RouteCriteriaTestFactory.createGrpc(); + public static GrpcRouteForwardingRequest create() { return createBuilder().build(); } public static GrpcRouteForwardingRequest.Builder createBuilder() { return GrpcRouteForwardingRequest.newBuilder() - .setRouteCriteria(RouteCriteriaTestFactory.createGrpc()); + .setEingang(EINGANG) + .setRouteCriteria(CRITERIA); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java index e4dd78ddb..e165091ee 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java @@ -23,19 +23,17 @@ */ package de.ozgcloud.eingang.forwarder; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.mapstruct.factory.Mappers; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; import de.ozgcloud.eingang.router.GrpcEingangMapper; import io.grpc.stub.StreamObserver; @@ -50,39 +48,42 @@ class RouteForwardingGrpcServiceTest { @Mock private RouteForwardingService routeService; - @Spy - private RouteCriteriaMapper criteriaMapper = Mappers.getMapper(RouteCriteriaMapper.class); - @Spy - private GrpcEingangMapper eingangMapper = Mappers.getMapper(GrpcEingangMapper.class); + @Mock + private RouteCriteriaMapper criteriaMapper; + @Mock + private GrpcEingangMapper eingangMapper; @Nested class TestRouteForwarding { - @Captor - private ArgumentCaptor<RouteCriteria> criteriaCaptor; + private final RouteCriteria routeCriteria = RouteCriteriaTestFactory.create(); + private final FormData formData = FormDataTestFactory.create(); + + @BeforeEach + void mock() { + when(criteriaMapper.fromGrpc(any())).thenReturn(routeCriteria); + when(eingangMapper.toFormData(any())).thenReturn(formData); + } @Test - void shouldCallService() { + void shouldMapCriteria() { service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); - verify(routeService).route(any(), any()); + verify(criteriaMapper).fromGrpc(GrpcRouteForwardingRequestTestFactory.CRITERIA); } @Test - void shouldHaveRouteCriteria() { + void shouldMapEingang() { service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); - verify(routeService).route(criteriaCaptor.capture(), any()); - - assertThat(criteriaCaptor.getValue()).usingRecursiveComparison().isEqualTo(RouteCriteriaTestFactory.create()); + verify(eingangMapper).toFormData(GrpcRouteForwardingRequestTestFactory.EINGANG); } @Test - void shouldHaveFormData() { + void shouldCallService() { service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); - verify(routeService).route(any(), notNull()); - verify(eingangMapper).toFormData(any()); + verify(routeService).route(routeCriteria, formData); } } diff --git a/pom.xml b/pom.xml index ce7c182f5..4eb2c2578 100644 --- a/pom.xml +++ b/pom.xml @@ -126,6 +126,13 @@ <scope>test</scope> <version>${project.version}</version> </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>router</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> <dependency> <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-utils</artifactId> diff --git a/router/pom.xml b/router/pom.xml index 7130d2c1e..5964dfb91 100644 --- a/router/pom.xml +++ b/router/pom.xml @@ -92,10 +92,28 @@ <type>test-jar</type> <scope>test</scope> </dependency> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-utils</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> <build> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperITCase.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperITCase.java index 55e1b3ef3..758fcd0ef 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperITCase.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperITCase.java @@ -29,7 +29,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -38,6 +37,7 @@ import org.springframework.boot.test.context.SpringBootTest; import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelleTestFactory; import de.ozgcloud.vorgang.vorgang.GrpcEingang; @@ -59,7 +59,9 @@ class GrpcEingangMapperITCase { @Test void antragstellerShouldBeMapped() { - var antragSteller = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)).getAntragsteller(); + var antragSteller = grpcEingangMapper + .toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)) + .getAntragsteller(); assertThat(antragSteller.getPostfachId()).isEqualTo(AntragstellerTestFactory.POSTFACH_ID); assertThat(antragSteller.getVorname()).isEqualTo(AntragstellerTestFactory.VORNAME); @@ -68,7 +70,9 @@ class GrpcEingangMapperITCase { @Test void dataShouldBeMapped() { - var antragsteller = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)).getAntragsteller(); + var antragsteller = grpcEingangMapper + .toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)) + .getAntragsteller(); assertThat(antragsteller.getOtherData().getFieldList()).hasSize(1); assertThat(antragsteller.getOtherData().getField(0).getName()).isEqualTo(AntragstellerTestFactory.GEBIET_BEZEICHNUNG_KEY); @@ -81,7 +85,9 @@ class GrpcEingangMapperITCase { class TestZustaendigeStelle { @Test void eingangShouldHaveZustaendigeStelle() { - var zustaendigeStelle = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)).getZustaendigeStelle(); + var zustaendigeStelle = grpcEingangMapper + .toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)) + .getZustaendigeStelle(); assertThat(zustaendigeStelle).isNotNull(); assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID); @@ -102,34 +108,30 @@ class GrpcEingangMapperITCase { @DisplayName("Test mapped Attachments") class TestAttachments { - private GrpcEingang eingang; - - @BeforeEach - void init() { - - eingang = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.empty()); - } - @Test void validateNumberOfAttachments() { + var eingang = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.empty()); - assertThat(eingang.getNumberOfAttachments()).isEqualTo(2); + assertThat(eingang.getNumberOfAttachments()).isEqualTo(FormDataTestFactory.ATTACHMENTS.size()); } @Test void validateNumberOfAttachmentGroups() { + var eingang = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.empty()); - assertThat(eingang.getAttachmentsCount()).isEqualTo(2); + assertThat(eingang.getAttachmentsCount()).isEqualTo(FormDataTestFactory.ATTACHMENTS.size()); } @Test void validateGroup1AttachmentCount() { + var eingang = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.empty()); assertThat(eingang.getAttachmentsList().get(0).getFilesCount()).isEqualTo(1); } @Test void validateGroup1Attachment() { + var eingang = grpcEingangMapper.toEingang(FormDataTestFactory.create(), Optional.empty()); GrpcIncomingFile attachment = eingang.getAttachmentsList().get(0).getFilesList().get(0); @@ -142,12 +144,18 @@ class GrpcEingangMapperITCase { @Test void validateGroup2AttachmentCount() { + var attachmentGroup2 = IncomingFileGroupTestFactory.createBuilder().name("attachmentGroup2").build(); + + var eingang = grpcEingangMapper.toEingang(FormDataTestFactory.createBuilder().attachment(attachmentGroup2).build(), Optional.empty()); assertThat(eingang.getAttachmentsList().get(1).getFilesCount()).isEqualTo(1); } @Test void validateGroup2Attachment() { + var attachmentGroup2 = IncomingFileGroupTestFactory.createBuilder().name("attachmentGroup2").build(); + + var eingang = grpcEingangMapper.toEingang(FormDataTestFactory.createBuilder().attachment(attachmentGroup2).build(), Optional.empty()); GrpcIncomingFile attachment = eingang.getAttachmentsList().get(1).getFilesList().get(0); @@ -187,7 +195,8 @@ class GrpcEingangMapperITCase { void valueListShouldGenerateFields() { GrpcEingang eingang = grpcEingangMapper - .toEingang(FormDataTestFactory.createBuilder().formData(Map.of("key", List.of("value1", "value2"))).build(), Optional.empty()); + .toEingang(FormDataTestFactory.createBuilder().formData(Map.of("key", List.of("value1", "value2"))).build(), + Optional.empty()); assertThat(eingang.getFormData().getFieldCount()).isEqualTo(2); } @@ -197,7 +206,8 @@ class GrpcEingangMapperITCase { GrpcEingang eingang = grpcEingangMapper .toEingang(FormDataTestFactory.createBuilder() - .formData(Map.of("key-1", List.of(Map.of("sub_key", "value1"), Map.of("sub_key", "value2")))).build(), Optional.empty()); + .formData(Map.of("key-1", List.of(Map.of("sub_key", "value1"), Map.of("sub_key", "value2")))).build(), + Optional.empty()); assertThat(eingang.getFormData().getFormCount()).isEqualTo(2); assertThat(eingang.getFormData().getForm(0).getFieldCount()).isEqualTo(1); diff --git a/router/src/test/java/de/ozgcloud/eingang/router/VorgangServiceTest.java b/router/src/test/java/de/ozgcloud/eingang/router/VorgangServiceTest.java index d69b36c66..bd5ff001a 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/VorgangServiceTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/VorgangServiceTest.java @@ -27,6 +27,8 @@ import static de.ozgcloud.eingang.common.formdata.FormDataTestFactory.*; import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import java.io.IOException; @@ -152,7 +154,7 @@ class VorgangServiceTest { void shouldReturnAttachmentsAndRepresentations() { var files = service.getFormDataFiles(formData).toList(); - assertThat(files).hasSize(3); + assertThat(files).hasSize(FormDataTestFactory.ATTACHMENTS.size() + FormDataTestFactory.REPRESENTATIONS.size()); } } -- GitLab From cea513cccab8a1ee19cd7d292454869220916120 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Wed, 12 Mar 2025 17:32:41 +0100 Subject: [PATCH 05/28] OZG-7573 fix test after test factory change --- .../ozgcloud/eingang/semantik/common/FormDataTestFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java index 8576eb31d..83b265781 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java @@ -5,10 +5,11 @@ import java.util.List; import java.util.Map; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; public class FormDataTestFactory { public static final String POSTFACH_NAME_ID = "name-id-value"; - public static final int REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE_VALUE = 1; + public static final int REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE_VALUE = PostfachAddressTestFactory.POSTFACH_ADDRESS_TYPE; public static FormData create() { return createBuilder().build(); -- GitLab From 776814b0ed6b2c0ed639ae251a4d2dabeee2d38a Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Fri, 14 Mar 2025 16:10:15 +0100 Subject: [PATCH 06/28] OZG-7573 add eingang-manager-interface module --- eingang-manager-interface/pom.xml | 174 ++++++++++++++++++ .../src/main/protobuf/common.model.proto | 46 +++++ .../src/main/protobuf/forwarding.model.proto | 144 +++++++++++++++ .../src/main/protobuf/forwarding.proto | 39 ++++ 4 files changed, 403 insertions(+) create mode 100644 eingang-manager-interface/pom.xml create mode 100644 eingang-manager-interface/src/main/protobuf/common.model.proto create mode 100644 eingang-manager-interface/src/main/protobuf/forwarding.model.proto create mode 100644 eingang-manager-interface/src/main/protobuf/forwarding.proto diff --git a/eingang-manager-interface/pom.xml b/eingang-manager-interface/pom.xml new file mode 100644 index 000000000..dc3858f82 --- /dev/null +++ b/eingang-manager-interface/pom.xml @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (C) 2023 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-dependencies</artifactId> + <version>4.11.0</version> + <relativePath /> + </parent> + + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>eingang-manager-interface</artifactId> + <version>2.19.0-SNAPSHOT</version> + + <name>OZG-Cloud Eingang Manager gRPC Interface</name> + <description>Interface (gRPC) for Eingang Manager Server</description> + <inceptionYear>2025</inceptionYear> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <java.version>21</java.version> + <maven.compiler.source>${java.version}</maven.compiler.source> + <maven.compiler.target>${java.version}</maven.compiler.target> + + <find-and-replace-maven-plugin.version>1.1.0</find-and-replace-maven-plugin.version> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-dependencies</artifactId> + <version>${ozgcloud-common.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <!-- GRPC --> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-stub</artifactId> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-protobuf</artifactId> + </dependency> + <dependency> + <groupId>jakarta.annotation</groupId> + <artifactId>jakarta.annotation-api</artifactId> + </dependency> + </dependencies> + + <build> + <sourceDirectory>src/main/protobuf</sourceDirectory> + + <extensions> + <extension> + <groupId>kr.motd.maven</groupId> + <artifactId>os-maven-plugin</artifactId> + </extension> + </extensions> + + <plugins> + <plugin> + <groupId>com.github.os72</groupId> + <artifactId>protoc-jar-maven-plugin</artifactId> + <version>${protoc-jar-plugin.version}</version> + <executions> + <execution> + <phase>generate-sources</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <protocVersion>${protobuf.version}</protocVersion> + <outputTargets> + <outputTarget> + <type>java</type> + </outputTarget> + <outputTarget> + <type>grpc-java</type> + <pluginArtifact> + io.grpc:protoc-gen-grpc-java:${protoc-gen.version}</pluginArtifact> + </outputTarget> + </outputTargets> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>io.github.floverfelt</groupId> + <artifactId>find-and-replace-maven-plugin</artifactId> + <version>${find-and-replace-maven-plugin.version}</version> + <executions> + <execution> + <id>exec</id> + <phase>process-sources</phase> + <goals> + <goal>find-and-replace</goal> + </goals> + <configuration> + <replacementType>file-contents</replacementType> + <baseDir>target/generated-sources/</baseDir> + <findRegex>javax</findRegex> + <replaceValue>jakarta</replaceValue> + <recursive>true</recursive> + <fileMask>.java</fileMask> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.1</version> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <distributionManagement> + <repository> + <id>ozg-nexus</id> + <name>ozg-releases</name> + <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url> + </repository> + <snapshotRepository> + <id>ozg-snapshots-nexus</id> + <name>ozg-snapshots</name> + <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url> + </snapshotRepository> + </distributionManagement> +</project> \ No newline at end of file diff --git a/eingang-manager-interface/src/main/protobuf/common.model.proto b/eingang-manager-interface/src/main/protobuf/common.model.proto new file mode 100644 index 000000000..25067f3e9 --- /dev/null +++ b/eingang-manager-interface/src/main/protobuf/common.model.proto @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 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. + */ +syntax = "proto3"; + +package de.ozgcloud.eingang.common; + +option java_multiple_files = true; +option java_package = "de.ozgcloud.eingang.common"; +option java_outer_classname = "CommonModelProto"; + +message GrpcObject { + repeated GrpcProperty property = 1; + repeated GrpcSubObject subObject = 2; +} + +message GrpcProperty { + string name = 1; + repeated string value = 2; +} + +message GrpcSubObject { + string name = 1; + repeated GrpcProperty property = 2; + repeated GrpcSubObject subObject = 3; +} \ No newline at end of file diff --git a/eingang-manager-interface/src/main/protobuf/forwarding.model.proto b/eingang-manager-interface/src/main/protobuf/forwarding.model.proto new file mode 100644 index 000000000..64a281597 --- /dev/null +++ b/eingang-manager-interface/src/main/protobuf/forwarding.model.proto @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2023 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. + */ +syntax = "proto3"; + +package de.ozgcloud.eingang.forwarder; + +import "common.model.proto"; + +option java_multiple_files = true; +option java_package = "de.ozgcloud.eingang.forwarding"; +option java_outer_classname = "RouteForwardingModelProto"; + + +message GrpcRouteForwardingRequest { + oneof request { + GrpcRouteForwarding routeForwarding = 1; + GrpcAttachment attachment = 2; + GrpcRepresentation representation = 3; + } +} + +message GrpcRouteForwardingResponse { + +} + +message GrpcRouteForwarding { + GrpcEingangStub eingangStub = 1; + GrpcRouteCriteria routeCriteria = 2; +} + +message GrpcEingangStub { + GrpcEingangHeader header = 1; + GrpcAntragsteller antragsteller = 2; + GrpcFormData formData = 3; +} + +message GrpcEingangHeader { + string requestId = 1; + string vorgangNummer = 2; + string createdAt = 3; + string formId = 4; + string formName = 5; + string formEngineName = 6; + string sender = 7; + GrpcServiceKonto serviceKonto = 8; +} + +message GrpcServiceKonto { + string type = 1; + repeated GrpcPostfachAddress postfachAddresses = 2; + string trustLevel = 3; +} + +message GrpcPostfachAddress { + string version = 1; + de.ozgcloud.eingang.common.GrpcObject identifier = 2; + int32 type = 3; +} + +message GrpcAntragsteller { + string anrede = 1; + string nachname = 2; + string vorname = 3; + string geburtsdatum = 4; + string geburtsort = 5; + string geburtsname = 6; + string email = 7; + string telefon = 8; + string strasse = 9; + string hausnummer = 10; + string plz = 11; + string ort = 12; + GrpcFormData data = 13; + string firmaName = 14; +} + +message GrpcFormData { + repeated GrpcFormField field = 1; + repeated GrpcFormData form = 2; +} + +message GrpcFormField { + string name = 1; + string value = 2; +} + +message GrpcRouteCriteria { + string organisationseinheitenId = 1; +} + +message GrpcAttachment { + oneof attachment { + GrpcAttachmentFile file = 1; + GrpcFileContent content = 2; + } +} + +message GrpcAttachmentFile { + string groupName = 1; + string fileName = 2; + string contentType = 3; + string vendorId = 4; + int64 size = 5; +} + +message GrpcRepresentation { + oneof representation { + GrpcRepresentationFile file = 1; + GrpcFileContent content = 2; + } +} + +message GrpcRepresentationFile { + string fileName = 1; + string contentType = 2; + string vendorId = 3; + int64 size = 4; +} + +message GrpcFileContent { + bytes content = 1; + bool isEndOfFile = 2; +} \ No newline at end of file diff --git a/eingang-manager-interface/src/main/protobuf/forwarding.proto b/eingang-manager-interface/src/main/protobuf/forwarding.proto new file mode 100644 index 000000000..0d6c4100d --- /dev/null +++ b/eingang-manager-interface/src/main/protobuf/forwarding.proto @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 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. + */ +syntax = "proto3"; + +package de.ozgcloud.eingang.forwarder; + +import "forwarding.model.proto"; + +option java_multiple_files = true; +option java_package = "de.ozgcloud.eingang.forwarder"; +option java_outer_classname = "RouteForwardingProto"; + +service RouteForwardingService { + + rpc RouteForwarding(stream GrpcRouteForwardingRequest) returns (GrpcRouteForwardingResponse) { + } + +} \ No newline at end of file -- GitLab From aee9317056988bf957670e61ac25ab7226166efe Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Fri, 14 Mar 2025 16:13:31 +0100 Subject: [PATCH 07/28] OZG-7573 add poc version for EingangStubReceiverStreamObserver --- forwarder/pom.xml | 4 + .../EingangStubReceiverStreamObserver.java | 200 ++++++++++++++++++ .../forwarder/IncomingFileGroupMapper.java | 15 ++ .../eingang/forwarder/IncomingFileMapper.java | 22 ++ .../eingang/forwarder/RouteCriteria.java | 2 - .../forwarder/RouteForwardingGrpcService.java | 8 +- .../forwarder/RouteForwardingMapper.java | 54 +++++ ...GrpcRouteForwardingRequestTestFactory.java | 4 +- .../forwarder/RouteCriteriaTestFactory.java | 9 +- .../RouteForwardingGrpcServiceTest.java | 34 +-- pom.xml | 10 +- router/pom.xml | 5 + 12 files changed, 335 insertions(+), 32 deletions(-) create mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java create mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java create mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java create mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java diff --git a/forwarder/pom.xml b/forwarder/pom.xml index d79e4343e..4fabecd6a 100644 --- a/forwarder/pom.xml +++ b/forwarder/pom.xml @@ -49,6 +49,10 @@ <groupId>de.ozgcloud.eingang</groupId> <artifactId>common</artifactId> </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>eingang-manager-interface</artifactId> + </dependency> <dependency> <groupId>de.ozgcloud.eingang</groupId> <artifactId>router</artifactId> diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java new file mode 100644 index 000000000..13044c3f5 --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -0,0 +1,200 @@ +package de.ozgcloud.eingang.forwarder; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.apache.commons.io.IOUtils; + +import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.forwarding.GrpcAttachment; +import de.ozgcloud.eingang.forwarding.GrpcFileContent; +import de.ozgcloud.eingang.forwarding.GrpcRepresentation; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; +import io.grpc.stub.StreamObserver; +import lombok.Builder; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwardingRequest> { + + private static final int CHUNK_SIZE = 1024 * 64; + private static final long TIMEOUT_MINUTES = 10; + private final RouteForwardingMapper routeForwardingMapper; + private final IncomingFileMapper incomingFileMapper; + private final IncomingFileGroupMapper incomingFileGroupMapper; + private final Function<InputStream, CompletableFuture<File>> fileSaver; + private final Consumer<FormData> formDataConsumer; + + @Builder + public EingangStubReceiverStreamObserver(RouteForwardingMapper routeForwardingMapper, IncomingFileMapper incomingFileMapper, + IncomingFileGroupMapper incomingFileGroupMapper, Function<InputStream, CompletableFuture<File>> fileSaver, + Consumer<FormData> formDataConsumer) { + this.routeForwardingMapper = routeForwardingMapper; + this.incomingFileMapper = incomingFileMapper; + this.incomingFileGroupMapper = incomingFileGroupMapper; + this.fileSaver = fileSaver; + this.formDataConsumer = formDataConsumer; + } + + private FormData formData; + private List<IncomingFile> representations = new ArrayList<>(); + private Map<String, List<IncomingFile>> attachments = new HashMap<>(); + + private IncomingFile currentFile; + private Optional<String> groupName = Optional.empty(); + private PipedOutputStream pipedOutput; + private PipedInputStream pipedInput; + private CompletableFuture<File> receivingFileContent; + + @Override + public synchronized void onNext(GrpcRouteForwardingRequest request) { + if (request.hasRouteForwarding()) { + handleRouteForwarding(request.getRouteForwarding()); + } + if (request.hasAttachment()) { + handleAttachment(request.getAttachment()); + } + if (request.hasRepresentation()) { + handleRepresentation(request.getRepresentation()); + } + } + + private void handleRouteForwarding(GrpcRouteForwarding routeForwarding) { + if (Objects.nonNull(formData)) { + throw new IllegalStateException("Received second RouteForwarding. Send only one per request."); + } + formData = routeForwardingMapper.toFormData(routeForwarding.getEingangStub(), routeForwarding.getRouteCriteria()); + } + + private void handleAttachment(GrpcAttachment attachment) { + if (attachment.hasFile()) { + setCurrentMetadata(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); + groupName = Optional.of(attachment.getFile().getGroupName()); + } else { + if (Objects.isNull(receivingFileContent)) { + initContentReceiving(); + } + storeFileContent(attachment.getContent()); + } + } + + private void handleRepresentation(GrpcRepresentation representation) { + if (representation.hasFile()) { + setCurrentMetadata(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); + } else { + if (Objects.isNull(receivingFileContent)) { + initContentReceiving(); + } + storeFileContent(representation.getContent()); + } + + } + + private void setCurrentMetadata(IncomingFile metaData) { + if (Objects.nonNull(currentFile)) { + throw new TechnicalException("Received additional file before previos file reached the end."); + } + currentFile = metaData; + } + + private void initContentReceiving() { + try { + pipedInput = new PipedInputStream(CHUNK_SIZE); + pipedOutput = new PipedOutputStream(pipedInput); + receivingFileContent = fileSaver.apply(pipedInput); + } catch (IOException e) { + throw new TechnicalException("Upload initialization failed", e); + } + } + + private void storeFileContent(GrpcFileContent content) { + if (Objects.isNull(currentFile)) { + throw new TechnicalException("File content received before metadata."); + } + try { + pipedOutput.write(content.getContent().toByteArray()); + if (content.getIsEndOfFile()) { + handleEndOfFile(); + } + } catch (IOException e) { + throw new TechnicalException("Error when writing file content.", e); + } + } + + private void handleEndOfFile() { + closeOutputPipe(); + var completedIncomingFile = currentFile.toBuilder().file(getSavedFileContent()).build(); + groupName.map(group -> attachments.get(group)).orElse(representations).add(completedIncomingFile); + resetFileReceiving(); + } + + private File getSavedFileContent() { + try { + return receivingFileContent.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); + } catch (ExecutionException | TimeoutException e) { + throw new TechnicalException("Receiving file failed.", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TechnicalException("Upload was interrupted.", e); + } finally { + closeInputPipe(); + } + } + + private void resetFileReceiving() { + currentFile = null; + groupName = Optional.empty(); + pipedOutput = null; + pipedInput = null; + receivingFileContent = null; + } + + @Override + public void onError(Throwable t) { + LOG.error("Error happened. Receiving stream closed.", t); + closeOutputPipe(); + closeInputPipe(); + } + + private void closeOutputPipe() { + IOUtils.closeQuietly(pipedOutput, e -> LOG.error("Cannot close output stream.", e)); + } + + private void closeInputPipe() { + IOUtils.closeQuietly(pipedInput, e -> LOG.error("Cannot close input stream.", e)); + } + + @Override + public void onCompleted() { + formDataConsumer.accept(assembleFormData()); + } + + private FormData assembleFormData() { + if (Objects.isNull(formData)) { + throw new IllegalStateException("Never received RouteForwarding containing EingangStub and RouteCriteria."); + } + return formData.toBuilder() + .representations(representations) + .attachments(attachments.entrySet().stream().map(incomingFileGroupMapper::fromMapEntry).toList()) + .build(); + } + +} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java new file mode 100644 index 000000000..7f35ef41d --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java @@ -0,0 +1,15 @@ +package de.ozgcloud.eingang.forwarder; + +import java.util.List; +import java.util.Map; + +import org.mapstruct.Mapper; + +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; + +@Mapper +public interface IncomingFileGroupMapper { + + IncomingFileGroup fromMapEntry(Map.Entry<String, List<IncomingFile>> entry); // TODO: Implement this method +} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java new file mode 100644 index 000000000..26e3ceddd --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java @@ -0,0 +1,22 @@ +package de.ozgcloud.eingang.forwarder; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile; +import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile; + +@Mapper +interface IncomingFileMapper { + + @Mapping(target = "id", ignore = true) + @Mapping(target = "file", ignore = true) + @Mapping(target = "name", source = "fileName") + IncomingFile fromGrpcRepresentationFile(GrpcRepresentationFile representationFile); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "file", ignore = true) + @Mapping(target = "name", source = "fileName") + IncomingFile fromGrpcAttachmentFile(GrpcAttachmentFile representationFile); +} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java index 3a36486c9..65583d7cf 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java @@ -32,7 +32,5 @@ import lombok.Getter; @Builder public class RouteCriteria { - private Optional<String> gemeindeSchluessel; - private Optional<String> webserviceUrl; private Optional<String> organisationEinheitId; } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java index 6827f8839..82f8ae332 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java @@ -40,7 +40,11 @@ public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.Route private final GrpcEingangMapper eingangMapper; @Override - public void routeForwarding(GrpcRouteForwardingRequest request, StreamObserver<GrpcRouteForwardingResponse> responseObserver) { - service.route(criteriaMapper.fromGrpc(request.getRouteCriteria()), eingangMapper.toFormData(request.getEingang())); + public StreamObserver<GrpcRouteForwardingRequest> routeForwarding(StreamObserver<GrpcRouteForwardingResponse> responseObserver) { + // public void routeForwarding(GrpcRouteForwardingRequest request, + // StreamObserver<GrpcRouteForwardingResponse> responseObserver) { + // service.route(criteriaMapper.fromGrpc(request.getRouteCriteria()), + // eingangMapper.toFormData(request.getEingang())); + return null; } } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java new file mode 100644 index 000000000..315ba8131 --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 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.eingang.forwarder; + +import java.util.Map; + +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.ReportingPolicy; + +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.forwarding.GrpcEingangStub; +import de.ozgcloud.eingang.forwarding.GrpcFormData; +import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public interface RouteForwardingMapper { + + @Mapping(target = "attachments", ignore = true) + @Mapping(target = "representations", ignore = true) + @Mapping(target = "control", ignore = true) + FormData toFormData(GrpcEingangStub eingangStub, GrpcRouteCriteria routeCriteria); // TODO: Test + + default Map<String, Object> map(GrpcFormData value) { + return null; // TODO: Implement + }; +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java index 37f758e1d..ddd6a44d2 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java @@ -38,8 +38,6 @@ public class GrpcRouteForwardingRequestTestFactory { } public static GrpcRouteForwardingRequest.Builder createBuilder() { - return GrpcRouteForwardingRequest.newBuilder() - .setEingang(EINGANG) - .setRouteCriteria(CRITERIA); + return GrpcRouteForwardingRequest.newBuilder(); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java index 82a9dc490..49c265a75 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java @@ -24,14 +24,13 @@ package de.ozgcloud.eingang.forwarder; import java.util.Optional; +import java.util.UUID; import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; public class RouteCriteriaTestFactory { - public static final String GEMEINDE_SCHLUSSEL = "0815"; - public static final String WEBSERVICE_URL = "http://nimmerland.by.kop-cloud.de/ws"; - public static final String ORGANISATION_EINHEIT_ID = "4711"; + public static final String ORGANISATION_EINHEIT_ID = UUID.randomUUID().toString(); public static RouteCriteria create() { return createBuilder().build(); @@ -39,8 +38,6 @@ public class RouteCriteriaTestFactory { public static RouteCriteria.RouteCriteriaBuilder createBuilder() { return RouteCriteria.builder() - .gemeindeSchluessel(Optional.of(GEMEINDE_SCHLUSSEL)) - .webserviceUrl(Optional.of(WEBSERVICE_URL)) .organisationEinheitId(Optional.of(ORGANISATION_EINHEIT_ID)); } @@ -50,8 +47,6 @@ public class RouteCriteriaTestFactory { public static GrpcRouteCriteria.Builder createGrpcBuilder() { return GrpcRouteCriteria.newBuilder() - .setGemeindeSchluessel(GEMEINDE_SCHLUSSEL) - .setWebserviceUrl(WEBSERVICE_URL) .setOrganisationseinheitenId(ORGANISATION_EINHEIT_ID); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java index e165091ee..f4f0b4f64 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java @@ -28,7 +28,6 @@ import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -65,26 +64,29 @@ class RouteForwardingGrpcServiceTest { when(eingangMapper.toFormData(any())).thenReturn(formData); } - @Test - void shouldMapCriteria() { - service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); + // @Test + // void shouldMapCriteria() { + // service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), + // responseObserver); - verify(criteriaMapper).fromGrpc(GrpcRouteForwardingRequestTestFactory.CRITERIA); - } + // verify(criteriaMapper).fromGrpc(GrpcRouteForwardingRequestTestFactory.CRITERIA); + // } - @Test - void shouldMapEingang() { - service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); + // @Test + // void shouldMapEingang() { + // service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), + // responseObserver); - verify(eingangMapper).toFormData(GrpcRouteForwardingRequestTestFactory.EINGANG); - } + // verify(eingangMapper).toFormData(GrpcRouteForwardingRequestTestFactory.EINGANG); + // } - @Test - void shouldCallService() { - service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); + // @Test + // void shouldCallService() { + // service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), + // responseObserver); - verify(routeService).route(routeCriteria, formData); - } + // verify(routeService).route(routeCriteria, formData); + // } } } diff --git a/pom.xml b/pom.xml index 4eb2c2578..82d197342 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-parent</artifactId> - <version>4.9.0</version> + <version>4.11.0</version> <relativePath /> <!-- lookup parent from repository --> </parent> @@ -45,6 +45,7 @@ <modules> <module>common</module> + <module>eingang-manager-interface</module> <module>router</module> <module>forwarder</module> <module>semantik-adapter</module> @@ -54,7 +55,7 @@ </modules> <properties> - <vorgang-manager.version>2.10.0</vorgang-manager.version> + <vorgang-manager.version>2.24.0-OZG-7573-forwarding-interface-SNAPSHOT</vorgang-manager.version> <zufi-manager.version>1.7.0</zufi-manager.version> <jsoup.version>1.14.3</jsoup.version> @@ -75,6 +76,11 @@ <artifactId>common</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>eingang-manager-interface</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>de.ozgcloud.eingang</groupId> <artifactId>router</artifactId> diff --git a/router/pom.xml b/router/pom.xml index 5964dfb91..95e980d63 100644 --- a/router/pom.xml +++ b/router/pom.xml @@ -73,6 +73,11 @@ <artifactId>commons-lang3</artifactId> </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct</artifactId> + </dependency> + <!-- Dev --> <dependency> <groupId>org.projectlombok</groupId> -- GitLab From 6352b83cdfee7fe1972344e1dfe236e511800016 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 10:32:43 +0100 Subject: [PATCH 08/28] OZG-7573 refactor EingangStubReceiverStreamObserver --- .../EingangStubReceiverStreamObserver.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 13044c3f5..202ab2ec4 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -28,6 +28,7 @@ import de.ozgcloud.eingang.forwarding.GrpcFileContent; import de.ozgcloud.eingang.forwarding.GrpcRepresentation; import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; import io.grpc.stub.StreamObserver; import lombok.Builder; import lombok.extern.log4j.Log4j2; @@ -42,16 +43,18 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou private final IncomingFileGroupMapper incomingFileGroupMapper; private final Function<InputStream, CompletableFuture<File>> fileSaver; private final Consumer<FormData> formDataConsumer; + private final Consumer<GrpcRouteForwardingResponse> responseConsumer; @Builder public EingangStubReceiverStreamObserver(RouteForwardingMapper routeForwardingMapper, IncomingFileMapper incomingFileMapper, IncomingFileGroupMapper incomingFileGroupMapper, Function<InputStream, CompletableFuture<File>> fileSaver, - Consumer<FormData> formDataConsumer) { + Consumer<FormData> formDataConsumer, Consumer<GrpcRouteForwardingResponse> responseConsumer) { this.routeForwardingMapper = routeForwardingMapper; this.incomingFileMapper = incomingFileMapper; this.incomingFileGroupMapper = incomingFileGroupMapper; this.fileSaver = fileSaver; this.formDataConsumer = formDataConsumer; + this.responseConsumer = responseConsumer; } private FormData formData; @@ -89,10 +92,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou setCurrentMetadata(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); groupName = Optional.of(attachment.getFile().getGroupName()); } else { - if (Objects.isNull(receivingFileContent)) { - initContentReceiving(); - } - storeFileContent(attachment.getContent()); + handleFileContent(attachment.getContent()); } } @@ -100,10 +100,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou if (representation.hasFile()) { setCurrentMetadata(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); } else { - if (Objects.isNull(receivingFileContent)) { - initContentReceiving(); - } - storeFileContent(representation.getContent()); + handleFileContent(representation.getContent()); } } @@ -115,6 +112,13 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou currentFile = metaData; } + private void handleFileContent(GrpcFileContent fileContent) { + if (Objects.isNull(receivingFileContent)) { + initContentReceiving(); + } + storeFileContent(fileContent); + } + private void initContentReceiving() { try { pipedInput = new PipedInputStream(CHUNK_SIZE); @@ -185,6 +189,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou @Override public void onCompleted() { formDataConsumer.accept(assembleFormData()); + responseConsumer.accept(GrpcRouteForwardingResponse.getDefaultInstance()); } private FormData assembleFormData() { -- GitLab From f897ea34166a5f67859e2bd11284b16f16ed4106 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 10:33:32 +0100 Subject: [PATCH 09/28] OZG-7573 imlemet RouteForwardingGrpcService with EingangStubReceiverStreamObserver --- .../eingang/forwarder/FileService.java | 19 ++ .../forwarder/RouteForwardingGrpcService.java | 37 +++- .../forwarder/RouteForwardingService.java | 5 + .../RouteForwardingGrpcServiceTest.java | 172 +++++++++++++++--- 4 files changed, 195 insertions(+), 38 deletions(-) create mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java new file mode 100644 index 000000000..812748eb1 --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java @@ -0,0 +1,19 @@ +package de.ozgcloud.eingang.forwarder; + +import java.io.File; +import java.io.InputStream; +import java.util.concurrent.CompletableFuture; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +@Service +class FileService { + + @Async + public CompletableFuture<File> saveToFile(InputStream inputStream) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'saveToFile'"); + } + +} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java index 82f8ae332..322e7361f 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java @@ -23,9 +23,12 @@ */ package de.ozgcloud.eingang.forwarder; +import java.io.File; +import java.io.InputStream; +import java.util.concurrent.CompletableFuture; + import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; -import de.ozgcloud.eingang.router.GrpcEingangMapper; import io.grpc.stub.StreamObserver; import lombok.RequiredArgsConstructor; import net.devh.boot.grpc.server.service.GrpcService; @@ -34,17 +37,31 @@ import net.devh.boot.grpc.server.service.GrpcService; @RequiredArgsConstructor public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.RouteForwardingServiceImplBase { - private final RouteForwardingService service; - private final RouteCriteriaMapper criteriaMapper; - - private final GrpcEingangMapper eingangMapper; + private final RouteForwardingMapper routeForwardingMapper; + private final IncomingFileMapper incomingFileMapper; + private final IncomingFileGroupMapper incomingFileGroupMapper; + private final RouteForwardingService routeForwardingService; + private final FileService fileService; @Override public StreamObserver<GrpcRouteForwardingRequest> routeForwarding(StreamObserver<GrpcRouteForwardingResponse> responseObserver) { - // public void routeForwarding(GrpcRouteForwardingRequest request, - // StreamObserver<GrpcRouteForwardingResponse> responseObserver) { - // service.route(criteriaMapper.fromGrpc(request.getRouteCriteria()), - // eingangMapper.toFormData(request.getEingang())); - return null; + return EingangStubReceiverStreamObserver.builder() + .fileSaver(this::saveFile) + .routeForwardingMapper(routeForwardingMapper) + .incomingFileMapper(incomingFileMapper) + .incomingFileGroupMapper(incomingFileGroupMapper) + .formDataConsumer(routeForwardingService::route) + .responseConsumer(repsonse -> respondWith(responseObserver, repsonse)) + .build(); + } + + public CompletableFuture<File> saveFile(InputStream inputStream) { + return fileService.saveToFile(inputStream); } + + public void respondWith(StreamObserver<GrpcRouteForwardingResponse> responseObserver, GrpcRouteForwardingResponse response) { + responseObserver.onNext(response); + responseObserver.onCompleted(); + } + } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java index 8df1ca5ae..13058871d 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java @@ -45,4 +45,9 @@ class RouteForwardingService { .build()) .build()); } + + public void route(FormData formData) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'route'"); + } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java index f4f0b4f64..35ac8140c 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java @@ -23,70 +23,186 @@ */ package de.ozgcloud.eingang.forwarder; +import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import org.junit.jupiter.api.BeforeEach; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; + import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.test.util.ReflectionTestUtils; + +import com.thedeanda.lorem.LoremIpsum; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; -import de.ozgcloud.eingang.router.GrpcEingangMapper; import io.grpc.stub.StreamObserver; class RouteForwardingGrpcServiceTest { @InjectMocks + @Spy private RouteForwardingGrpcService service; @Mock private StreamObserver<GrpcRouteForwardingResponse> responseObserver; @Mock - private RouteForwardingService routeService; + private RouteForwardingMapper routeForwardingMapper; + @Mock + private IncomingFileMapper incomingFileMapper; @Mock - private RouteCriteriaMapper criteriaMapper; + private IncomingFileGroupMapper incomingFileGroupMapper; @Mock - private GrpcEingangMapper eingangMapper; + private RouteForwardingService routeForwardingService; + @Mock + private FileService fileService; @Nested class TestRouteForwarding { + private static final byte[] CONTENT = LoremIpsum.getInstance().getWords(5).getBytes(); + + private static final ByteArrayInputStream INPUT_STREAM = new ByteArrayInputStream(CONTENT); - private final RouteCriteria routeCriteria = RouteCriteriaTestFactory.create(); private final FormData formData = FormDataTestFactory.create(); - @BeforeEach - void mock() { - when(criteriaMapper.fromGrpc(any())).thenReturn(routeCriteria); - when(eingangMapper.toFormData(any())).thenReturn(formData); + @Test + void shouldSetFileSaver() { + var observer = service.routeForwarding(responseObserver); + + callFileSaver(observer); + verify(service).saveFile(INPUT_STREAM); + } + + @Test + void shouldSetRouteForwardingMapper() { + var observer = service.routeForwarding(responseObserver); + + assertThat(getRouteForwardingMapper(observer)).isEqualTo(routeForwardingMapper); + } + + @Test + void shouldSetIncomingFileMapper() { + var observer = service.routeForwarding(responseObserver); + + assertThat(getIncomingFileMapper(observer)).isEqualTo(incomingFileMapper); + } + + @Test + void shouldSetIncomingFileGroupMapper() { + var observer = service.routeForwarding(responseObserver); + + assertThat(getIncomingFileGroupMapper(observer)).isEqualTo(incomingFileGroupMapper); + } + + @Test + void shouldSetFormDataConsumer() { + var observer = service.routeForwarding(responseObserver); + + callFormDataConsumer(observer, formData); + verify(routeForwardingService).route(formData); + } + + @Test + void shouldSetResponseConsumer() { + var observer = service.routeForwarding(responseObserver); + + callResponseConsumer(observer, GrpcRouteForwardingResponse.getDefaultInstance()); + verify(service).respondWith(responseObserver, GrpcRouteForwardingResponse.getDefaultInstance()); + } + + @SuppressWarnings("unchecked") + private void callFileSaver(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { + var fileSaver = (Function<InputStream, CompletableFuture<File>>) ReflectionTestUtils.getField(uploadObserver, "fileSaver"); + fileSaver.apply(INPUT_STREAM); + } + + private RouteForwardingMapper getRouteForwardingMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { + var routeForwardingMapper = (RouteForwardingMapper) ReflectionTestUtils.getField(uploadObserver, "routeForwardingMapper"); + return routeForwardingMapper; + } + + private IncomingFileMapper getIncomingFileMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { + var incomingFileMapper = (IncomingFileMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileMapper"); + return incomingFileMapper; + } + + private IncomingFileGroupMapper getIncomingFileGroupMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { + var incomingFileGroupMapper = (IncomingFileGroupMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileGroupMapper"); + return incomingFileGroupMapper; + } + + @SuppressWarnings("unchecked") + private void callFormDataConsumer(StreamObserver<GrpcRouteForwardingRequest> uploadObserver, FormData formData) { + var formDataConsumer = (Consumer<FormData>) ReflectionTestUtils.getField(uploadObserver, "formDataConsumer"); + formDataConsumer.accept(formData); + } + + @SuppressWarnings("unchecked") + private void callResponseConsumer(StreamObserver<GrpcRouteForwardingRequest> uploadObserver, GrpcRouteForwardingResponse response) { + var responseConsumer = (Consumer<GrpcRouteForwardingResponse>) ReflectionTestUtils.getField(uploadObserver, "responseConsumer"); + responseConsumer.accept(response); } + } + + @Nested + class TestSaveFile { - // @Test - // void shouldMapCriteria() { - // service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), - // responseObserver); + @Mock + private InputStream inputStream; + @Mock + private CompletableFuture<File> fileFuture; - // verify(criteriaMapper).fromGrpc(GrpcRouteForwardingRequestTestFactory.CRITERIA); - // } + @Test + void shouldReturnNull() { + service.saveFile(inputStream); - // @Test - // void shouldMapEingang() { - // service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), - // responseObserver); + verify(fileService).saveToFile(inputStream); + } - // verify(eingangMapper).toFormData(GrpcRouteForwardingRequestTestFactory.EINGANG); - // } + @Test + void shouldReturnFileFuture() { + when(fileService.saveToFile(any())).thenReturn(fileFuture); - // @Test - // void shouldCallService() { - // service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), - // responseObserver); + var result = service.saveFile(inputStream); - // verify(routeService).route(routeCriteria, formData); - // } + assertThat(result).isSameAs(fileFuture); + } } + @Nested + class TestRespondWith { + + private GrpcRouteForwardingResponse response = GrpcRouteForwardingResponse.newBuilder().build(); + @Mock + private StreamObserver<GrpcRouteForwardingResponse> responseObserver; + + @Test + void shouldCallOnNext() { + service.respondWith(responseObserver, response); + + verify(responseObserver).onNext(response); + } + + @Test + void shouldCallOnCompletedAfterOnNext() { + var inOrder = inOrder(responseObserver); + + service.respondWith(responseObserver, response); + + inOrder.verify(responseObserver).onNext(response); + inOrder.verify(responseObserver).onCompleted(); + } + } } -- GitLab From b6babd90a0f0fa49473236ee9abc2452957905dc Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 10:46:33 +0100 Subject: [PATCH 10/28] OZG-7573 implement IncomingFileMapper --- .../GrpcAttachmentFileTestFactory.java | 26 ++++++++++++ .../GrpcRepresentationFileTestFactory.java | 21 ++++++++++ .../forwarder/IncomingFileMapperTest.java | 40 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java new file mode 100644 index 000000000..431f4e0db --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java @@ -0,0 +1,26 @@ +package de.ozgcloud.eingang.forwarder; + +import com.thedeanda.lorem.LoremIpsum; + +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile; +import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile.Builder; + +public class GrpcAttachmentFileTestFactory { + + public static final String GROUP_NAME = LoremIpsum.getInstance().getWords(1); + + public static GrpcAttachmentFile create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcAttachmentFile.newBuilder() + .setGroupName(GROUP_NAME) + .setFileName(IncomingFileTestFactory.NAME) + .setContentType(IncomingFileTestFactory.CONTENT_TYPE) + .setVendorId(IncomingFileTestFactory.VENDOR_ID) + .setSize(IncomingFileTestFactory.SIZE); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java new file mode 100644 index 000000000..ce7fb5406 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java @@ -0,0 +1,21 @@ +package de.ozgcloud.eingang.forwarder; + +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile; +import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile.Builder; + +public class GrpcRepresentationFileTestFactory { + + public static GrpcRepresentationFile create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcRepresentationFile.newBuilder() + .setFileName(IncomingFileTestFactory.NAME) + .setContentType(IncomingFileTestFactory.CONTENT_TYPE) + .setVendorId(IncomingFileTestFactory.VENDOR_ID) + .setSize(IncomingFileTestFactory.SIZE); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java new file mode 100644 index 000000000..940332b66 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java @@ -0,0 +1,40 @@ +package de.ozgcloud.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; + +class IncomingFileMapperTest { + + private final IncomingFileMapper mapper = Mappers.getMapper(IncomingFileMapper.class); + + @Nested + class TestFromGrpcRepresentationFile { + @Test + void shouldMapToIncomingFile() { + var grpcRepresentationFile = GrpcRepresentationFileTestFactory.create(); + + var incomingFile = mapper.fromGrpcRepresentationFile(grpcRepresentationFile); + + assertThat(incomingFile).usingRecursiveComparison().ignoringFields("id", "file") + .isEqualTo(IncomingFileTestFactory.create()); + } + } + + @Nested + class TestFromGrpcAttachmentFile { + @Test + void shouldMapToIncomingFile() { + var grpcAttachmentFile = GrpcAttachmentFileTestFactory.create(); + + var incomingFile = mapper.fromGrpcAttachmentFile(grpcAttachmentFile); + + assertThat(incomingFile).usingRecursiveComparison().ignoringFields("id", "file") + .isEqualTo(IncomingFileTestFactory.create()); + } + } +} -- GitLab From ee192e1d0ab2edbc1e51bdac99e4e2dafded3ae4 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 11:10:34 +0100 Subject: [PATCH 11/28] OZG-7573 implement IncomingFileGroupMapper and clean up TestFactory --- .../IncomingFileGroupTestFactory.java | 21 ++++---------- .../formdata/IncomingFileTestFactory.java | 2 +- .../FormCycleFormDataTestFactory.java | 3 +- .../formcycle/FormDataControllerITCase.java | 13 ++++----- .../formcycle/FormDataControllerTest.java | 2 +- .../forwarder/IncomingFileGroupMapper.java | 7 ++++- .../IncomingFileGroupMapperTest.java | 29 +++++++++++++++++++ 7 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileGroupTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileGroupTestFactory.java index ebabd58ef..62d245773 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileGroupTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileGroupTestFactory.java @@ -25,23 +25,12 @@ package de.ozgcloud.eingang.common.formdata; import java.util.List; -public class IncomingFileGroupTestFactory { - public static final String XDOMEA_XML_NAME = "xdomea.xml"; - public static final String REPR_XML_NAME = "repr.xml"; - public static final String REPR_PDF_NAME = "repr.pdf"; - public static final String ATTATCHMENT_XML_NAME = "att.xml"; - public static final String ATTATCHMENT_PNG_NAME = "att.png"; - public static final String ATTATCHMENT_PDF_NAME = "att.pdf"; - - public static final String INCOMING_FILE_ID = "xxx"; - public static final String ID = "id"; - public static final String FILE_REF1 = "FileRef1"; - public static final String VENDOR_ID_XXX = "vendorId:xxx"; +import com.thedeanda.lorem.LoremIpsum; - public static final String NAME = "Ausweis"; +public class IncomingFileGroupTestFactory { - public static final IncomingFile INCOMING_FILE = IncomingFile.builder().id(INCOMING_FILE_ID).vendorId(VENDOR_ID_XXX).build(); - public static final List<IncomingFileGroup> FILE_GROUPS = List.of(IncomingFileGroup.builder().files(List.of(INCOMING_FILE)).build()); + public static final String NAME = LoremIpsum.getInstance().getWords(1); + public static final List<IncomingFile> INCOMING_FILES = List.of(IncomingFileTestFactory.create()); public static IncomingFileGroup create() { return createBuilder().build(); @@ -50,7 +39,7 @@ public class IncomingFileGroupTestFactory { public static IncomingFileGroup.IncomingFileGroupBuilder createBuilder() { return IncomingFileGroup.builder() .name(NAME) - .files(List.of(IncomingFileTestFactory.create())); + .files(INCOMING_FILES); } } diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java index 03fd99127..f377a61cd 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java @@ -35,7 +35,7 @@ import lombok.SneakyThrows; public class IncomingFileTestFactory { public static final String ID = UUID.randomUUID().toString(); - public static final String VENDOR_ID = IncomingFileGroupTestFactory.VENDOR_ID_XXX; + public static final String VENDOR_ID = "vendorId:xxx"; public static final String NAME = "XML-Daten.xml"; public static final String CONTENT_TYPE = "application/xml"; public static final String PDF_CONTENT_TYPE = MediaType.APPLICATION_PDF_VALUE; diff --git a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataTestFactory.java b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataTestFactory.java index 066b77ac5..edff3cd6c 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataTestFactory.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataTestFactory.java @@ -24,6 +24,7 @@ package de.ozgcloud.eingang.formcycle; import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.formcycle.FormCycleFormData.Builder; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory; import de.ozgcloud.vorgang.vorgang.GrpcFormData; @@ -43,7 +44,7 @@ public class FormCycleFormDataTestFactory { .setFormData(GrpcFormDataTestFactory.create()) .addAttachmentGroup(FormCycleAttachmentGroup.newBuilder() .setName(IncomingFileGroupTestFactory.NAME) - .addFileId(IncomingFileGroupTestFactory.VENDOR_ID_XXX) + .addFileId(IncomingFileTestFactory.VENDOR_ID) .build()); } diff --git a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerITCase.java b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerITCase.java index f63d7df6e..61daa9f4a 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerITCase.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerITCase.java @@ -37,7 +37,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import de.ozgcloud.common.test.ITCase; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.semantik.SemantikAdapter; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory; @@ -46,11 +45,11 @@ import de.ozgcloud.vorgang.vorgang.GrpcSubForm; import lombok.SneakyThrows; @ITCase -//@SpringBootTest(properties = { -// "grpc.client.vorgang-manager-local.address=static://127.0.0.1:9090", -// "grpc.client.vorgang-manager-local.negotiationType=PLAINTEXT" -//}) -//@ActiveProfiles("itcase") +// @SpringBootTest(properties = { +// "grpc.client.vorgang-manager-local.address=static://127.0.0.1:9090", +// "grpc.client.vorgang-manager-local.negotiationType=PLAINTEXT" +// }) +// @ActiveProfiles("itcase") @AutoConfigureMockMvc class FormDataControllerITCase { @@ -76,7 +75,7 @@ class FormDataControllerITCase { .file(new MockMultipartFile("formData", null, FormDataController.HTTP_TYPE_PROTOBUF, buildTestFormData())) .file(IncomingFileTestFactory.asMultipartFile("representations")) .file(asMultipartFile("attachments", - createBuilder().name(IncomingFileGroupTestFactory.VENDOR_ID_XXX + "__" + NAME).build()))); + createBuilder().name(IncomingFileTestFactory.VENDOR_ID + "__" + NAME).build()))); } } diff --git a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerTest.java b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerTest.java index af16a675d..e9fdd387f 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerTest.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormDataControllerTest.java @@ -239,7 +239,7 @@ class FormDataControllerTest { .file(new MockMultipartFile("formData", null, FormDataController.HTTP_TYPE_PROTOBUF, buildTestFormData())) .file(IncomingFileTestFactory.asMultipartFile("representations")) .file(asMultipartFile("attachments", - createBuilder().name(IncomingFileGroupTestFactory.VENDOR_ID_XXX).build()))); + createBuilder().name(IncomingFileTestFactory.VENDOR_ID).build()))); } } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java index 7f35ef41d..024d2c03e 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java @@ -11,5 +11,10 @@ import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; @Mapper public interface IncomingFileGroupMapper { - IncomingFileGroup fromMapEntry(Map.Entry<String, List<IncomingFile>> entry); // TODO: Implement this method + default IncomingFileGroup fromMapEntry(Map.Entry<String, List<IncomingFile>> entry) { + return IncomingFileGroup.builder() + .name(entry.getKey()) + .files(entry.getValue()) + .build(); + } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java new file mode 100644 index 000000000..acdc39b91 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java @@ -0,0 +1,29 @@ +package de.ozgcloud.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; + +class IncomingFileGroupMapperTest { + + private final IncomingFileGroupMapper mapper = Mappers.getMapper(IncomingFileGroupMapper.class); + + @Nested + class TestFromMapEntry { + + @Test + void shouldMapToIncomingFileGroup() { + var entry = Map.entry(IncomingFileGroupTestFactory.NAME, IncomingFileGroupTestFactory.INCOMING_FILES); + + var incomingFileGroup = mapper.fromMapEntry(entry); + + assertThat(incomingFileGroup).usingRecursiveComparison().isEqualTo(IncomingFileGroupTestFactory.create()); + } + } +} -- GitLab From d021a5d02b33a128d31f2467d135c8c79501b8ed Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 11:11:16 +0100 Subject: [PATCH 12/28] OZG-7573 set public methods synchronized in EingangStubReceiverStreamObserver --- .../eingang/forwarder/EingangStubReceiverStreamObserver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 202ab2ec4..4031741b0 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -172,7 +172,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } @Override - public void onError(Throwable t) { + public synchronized void onError(Throwable t) { LOG.error("Error happened. Receiving stream closed.", t); closeOutputPipe(); closeInputPipe(); @@ -187,7 +187,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } @Override - public void onCompleted() { + public synchronized void onCompleted() { formDataConsumer.accept(assembleFormData()); responseConsumer.accept(GrpcRouteForwardingResponse.getDefaultInstance()); } -- GitLab From c37d0fbe778208bc36661b448fb52091c2cc44e2 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 14:10:17 +0100 Subject: [PATCH 13/28] OZG-7573 use vorgang-maanger-interface proto messages --- eingang-manager-interface/pom.xml | 15 +++++ .../src/main/protobuf/common.model.proto | 46 --------------- ...arding.model.proto => forward.model.proto} | 58 ++----------------- .../{forwarding.proto => forward.proto} | 6 +- 4 files changed, 22 insertions(+), 103 deletions(-) delete mode 100644 eingang-manager-interface/src/main/protobuf/common.model.proto rename eingang-manager-interface/src/main/protobuf/{forwarding.model.proto => forward.model.proto} (65%) rename eingang-manager-interface/src/main/protobuf/{forwarding.proto => forward.proto} (90%) diff --git a/eingang-manager-interface/pom.xml b/eingang-manager-interface/pom.xml index dc3858f82..2aa828f6c 100644 --- a/eingang-manager-interface/pom.xml +++ b/eingang-manager-interface/pom.xml @@ -45,6 +45,7 @@ <inceptionYear>2025</inceptionYear> <properties> + <vorgang-manager.version>2.23.0</vorgang-manager.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> @@ -68,6 +69,19 @@ </dependencyManagement> <dependencies> + <!-- OZG-Cloud --> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-interface</artifactId> + <version>${vorgang-manager.version}</version> + </dependency> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-interface</artifactId> + <classifier>sources</classifier> + <scope>provided</scope> + <version>${vorgang-manager.version}</version> + </dependency> <!-- GRPC --> <dependency> <groupId>io.grpc</groupId> @@ -106,6 +120,7 @@ </goals> <configuration> <protocVersion>${protobuf.version}</protocVersion> + <includeMavenTypes>direct</includeMavenTypes> <outputTargets> <outputTarget> <type>java</type> diff --git a/eingang-manager-interface/src/main/protobuf/common.model.proto b/eingang-manager-interface/src/main/protobuf/common.model.proto deleted file mode 100644 index 25067f3e9..000000000 --- a/eingang-manager-interface/src/main/protobuf/common.model.proto +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2023 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. - */ -syntax = "proto3"; - -package de.ozgcloud.eingang.common; - -option java_multiple_files = true; -option java_package = "de.ozgcloud.eingang.common"; -option java_outer_classname = "CommonModelProto"; - -message GrpcObject { - repeated GrpcProperty property = 1; - repeated GrpcSubObject subObject = 2; -} - -message GrpcProperty { - string name = 1; - repeated string value = 2; -} - -message GrpcSubObject { - string name = 1; - repeated GrpcProperty property = 2; - repeated GrpcSubObject subObject = 3; -} \ No newline at end of file diff --git a/eingang-manager-interface/src/main/protobuf/forwarding.model.proto b/eingang-manager-interface/src/main/protobuf/forward.model.proto similarity index 65% rename from eingang-manager-interface/src/main/protobuf/forwarding.model.proto rename to eingang-manager-interface/src/main/protobuf/forward.model.proto index 64a281597..963450aa4 100644 --- a/eingang-manager-interface/src/main/protobuf/forwarding.model.proto +++ b/eingang-manager-interface/src/main/protobuf/forward.model.proto @@ -25,7 +25,7 @@ syntax = "proto3"; package de.ozgcloud.eingang.forwarder; -import "common.model.proto"; +import "vorgang.model.proto"; option java_multiple_files = true; option java_package = "de.ozgcloud.eingang.forwarding"; @@ -50,59 +50,9 @@ message GrpcRouteForwarding { } message GrpcEingangStub { - GrpcEingangHeader header = 1; - GrpcAntragsteller antragsteller = 2; - GrpcFormData formData = 3; -} - -message GrpcEingangHeader { - string requestId = 1; - string vorgangNummer = 2; - string createdAt = 3; - string formId = 4; - string formName = 5; - string formEngineName = 6; - string sender = 7; - GrpcServiceKonto serviceKonto = 8; -} - -message GrpcServiceKonto { - string type = 1; - repeated GrpcPostfachAddress postfachAddresses = 2; - string trustLevel = 3; -} - -message GrpcPostfachAddress { - string version = 1; - de.ozgcloud.eingang.common.GrpcObject identifier = 2; - int32 type = 3; -} - -message GrpcAntragsteller { - string anrede = 1; - string nachname = 2; - string vorname = 3; - string geburtsdatum = 4; - string geburtsort = 5; - string geburtsname = 6; - string email = 7; - string telefon = 8; - string strasse = 9; - string hausnummer = 10; - string plz = 11; - string ort = 12; - GrpcFormData data = 13; - string firmaName = 14; -} - -message GrpcFormData { - repeated GrpcFormField field = 1; - repeated GrpcFormData form = 2; -} - -message GrpcFormField { - string name = 1; - string value = 2; + de.ozgcloud.vorgang.vorgang.GrpcEingangHeader header = 1; + de.ozgcloud.vorgang.vorgang.GrpcAntragsteller antragsteller = 2; + de.ozgcloud.vorgang.vorgang.GrpcFormData formData = 3; } message GrpcRouteCriteria { diff --git a/eingang-manager-interface/src/main/protobuf/forwarding.proto b/eingang-manager-interface/src/main/protobuf/forward.proto similarity index 90% rename from eingang-manager-interface/src/main/protobuf/forwarding.proto rename to eingang-manager-interface/src/main/protobuf/forward.proto index 0d6c4100d..6d6085eba 100644 --- a/eingang-manager-interface/src/main/protobuf/forwarding.proto +++ b/eingang-manager-interface/src/main/protobuf/forward.proto @@ -25,7 +25,7 @@ syntax = "proto3"; package de.ozgcloud.eingang.forwarder; -import "forwarding.model.proto"; +import "forward.model.proto"; option java_multiple_files = true; option java_package = "de.ozgcloud.eingang.forwarder"; @@ -33,7 +33,7 @@ option java_outer_classname = "RouteForwardingProto"; service RouteForwardingService { - rpc RouteForwarding(stream GrpcRouteForwardingRequest) returns (GrpcRouteForwardingResponse) { - } + rpc RouteForwarding(stream GrpcRouteForwardingRequest) returns (GrpcRouteForwardingResponse) { + } } \ No newline at end of file -- GitLab From a4ec99d2d89a13094598aae050c3c8c1abef0ec6 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 14:52:01 +0100 Subject: [PATCH 14/28] OZG-7573 implement RouteForwardingMapper --- .../common/formdata/FormDataTestFactory.java | 6 +- .../src/main/protobuf/forward.model.proto | 2 +- .../EingangStubReceiverStreamObserver.java | 2 +- .../eingang/forwarder/RouteCriteria.java | 36 ------- .../forwarder/RouteCriteriaMapper.java | 43 -------- .../forwarder/RouteForwardingMapper.java | 36 ++++--- .../forwarder/RouteForwardingService.java | 20 ++-- .../forwarder/GrpcEingangStubTestFactory.java | 28 +++++ .../GrpcRouteCriteriaTestFactory.java | 21 ++++ ...GrpcRouteForwardingRequestTestFactory.java | 2 +- .../GrpcRouteForwardingTestFactory.java | 23 ++++ .../forwarder/RouteCriteriaTestFactory.java | 52 --------- .../forwarder/RouteForwardingMapperTest.java | 101 ++++++++++++++++++ .../forwarder/RouteForwardingServiceTest.java | 56 +++++----- .../eingang/router/ServiceKontoMapper.java | 4 +- 15 files changed, 241 insertions(+), 191 deletions(-) delete mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java delete mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java delete mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java index 94f756da0..2dc3a7f66 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java @@ -37,6 +37,8 @@ import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class FormDataTestFactory { + public static final Antragsteller ANTRAGSTELLER = AntragstellerTestFactory.create(); + public static final FormHeader HEADER = FormHeaderTestFactory.create(); public static final String ID = UUID.randomUUID().toString(); public static final String SIMPLE_VALUE_KEY = "kontaktsystemtypid"; public static final String SIMPLE_VALUE = "233034600"; @@ -76,8 +78,8 @@ public class FormDataTestFactory { public static FormData.FormDataBuilder createBuilder() { return FormData.builder() .id(ID) - .header(FormHeaderTestFactory.create()) - .antragsteller(AntragstellerTestFactory.create()) + .header(HEADER) + .antragsteller(ANTRAGSTELLER) .zustaendigeStelle(ZustaendigeStelleTestFactory.create()) .control(FORM_DATA_CONTROL) .formData(FORM_DATA) diff --git a/eingang-manager-interface/src/main/protobuf/forward.model.proto b/eingang-manager-interface/src/main/protobuf/forward.model.proto index 963450aa4..5b0c4a989 100644 --- a/eingang-manager-interface/src/main/protobuf/forward.model.proto +++ b/eingang-manager-interface/src/main/protobuf/forward.model.proto @@ -56,7 +56,7 @@ message GrpcEingangStub { } message GrpcRouteCriteria { - string organisationseinheitenId = 1; + string organisationEinheitId = 1; } message GrpcAttachment { diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 4031741b0..8f6381157 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -84,7 +84,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou if (Objects.nonNull(formData)) { throw new IllegalStateException("Received second RouteForwarding. Send only one per request."); } - formData = routeForwardingMapper.toFormData(routeForwarding.getEingangStub(), routeForwarding.getRouteCriteria()); + formData = routeForwardingMapper.toFormData(routeForwarding); } private void handleAttachment(GrpcAttachment attachment) { diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java deleted file mode 100644 index 65583d7cf..000000000 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2023 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.eingang.forwarder; - -import java.util.Optional; - -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class RouteCriteria { - - private Optional<String> organisationEinheitId; -} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java deleted file mode 100644 index 7fcb6cea6..000000000 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2023 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.eingang.forwarder; - -import java.util.Optional; - -import org.apache.commons.lang3.StringUtils; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; - -@Mapper -interface RouteCriteriaMapper { - - @Mapping(target = "organisationEinheitId", source = "organisationseinheitenId") - RouteCriteria fromGrpc(GrpcRouteCriteria grpcRouteCriteria); - - default Optional<String> wrapWithOptional(String val) { - return Optional.ofNullable(StringUtils.trimToNull(val)); - } -} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java index 315ba8131..5d519d5c9 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java @@ -23,32 +23,44 @@ */ package de.ozgcloud.eingang.forwarder; -import java.util.Map; - import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; -import org.mapstruct.ReportingPolicy; +import de.ozgcloud.eingang.common.formdata.Antragsteller; import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.forwarding.GrpcEingangStub; -import de.ozgcloud.eingang.forwarding.GrpcFormData; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.router.ServiceKontoMapper; +import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper; +import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; -@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // - nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // +@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, // + uses = { ServiceKontoMapper.class, GrpcFormDataMapper.class }) public interface RouteForwardingMapper { + @Mapping(target = "id", ignore = true) + @Mapping(target = "attachment", ignore = true) @Mapping(target = "attachments", ignore = true) + @Mapping(target = "numberOfAttachments", ignore = true) + @Mapping(target = "representation", ignore = true) @Mapping(target = "representations", ignore = true) + @Mapping(target = "numberOfRepresentations", ignore = true) @Mapping(target = "control", ignore = true) - FormData toFormData(GrpcEingangStub eingangStub, GrpcRouteCriteria routeCriteria); // TODO: Test + @Mapping(target = "zustaendigeStelles", ignore = true) + @Mapping(target = ".", source = "eingangStub") + @Mapping(target = "zustaendigeStelle", source = "routeCriteria") + FormData toFormData(GrpcRouteForwarding routeForwarding); + + @Mapping(target = "data", source = "otherData") + Antragsteller mapAntragstellerFromGrpc(GrpcAntragsteller antragsteller); - default Map<String, Object> map(GrpcFormData value) { - return null; // TODO: Implement - }; + default ZustaendigeStelle toZustaendigeStelle(GrpcRouteCriteria routeCriteria) { + return ZustaendigeStelle.builder().organisationseinheitenId(routeCriteria.getOrganisationEinheitId()).build(); + } } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java index 13058871d..8a455d31e 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java @@ -26,7 +26,6 @@ package de.ozgcloud.eingang.forwarder; import org.springframework.stereotype.Service; import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; import de.ozgcloud.eingang.router.VorgangService; import lombok.RequiredArgsConstructor; @@ -36,15 +35,16 @@ class RouteForwardingService { private final VorgangService vorgangService; - public void route(RouteCriteria criteria, FormData formData) { - vorgangService.createVorgang(formData.toBuilder() - .clearZustaendigeStelles() - .zustaendigeStelle(ZustaendigeStelle.builder() - .organisationseinheitenId(criteria.getOrganisationEinheitId() - .orElseThrow(() -> new UnsupportedOperationException("OrganisationseinheitId is required!"))) - .build()) - .build()); - } + // public void route(RouteCriteria criteria, FormData formData) { + // vorgangService.createVorgang(formData.toBuilder() + // .clearZustaendigeStelles() + // .zustaendigeStelle(ZustaendigeStelle.builder() + // .organisationseinheitenId(criteria.getOrganisationEinheitId() + // .orElseThrow(() -> new UnsupportedOperationException("OrganisationseinheitId + // is required!"))) + // .build()) + // .build()); + // } public void route(FormData formData) { // TODO Auto-generated method stub diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java new file mode 100644 index 000000000..ac07fe28f --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java @@ -0,0 +1,28 @@ +package de.ozgcloud.eingang.forwarder; + +import de.ozgcloud.eingang.forwarding.GrpcEingangStub; +import de.ozgcloud.eingang.forwarding.GrpcEingangStub.Builder; +import de.ozgcloud.eingang.router.GrpcAntragstellerTestFactory; +import de.ozgcloud.eingang.router.GrpcEingangHeaderTestFactory; +import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory; +import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; +import de.ozgcloud.vorgang.vorgang.GrpcEingangHeader; +import de.ozgcloud.vorgang.vorgang.GrpcFormData; + +public class GrpcEingangStubTestFactory { + + public static final GrpcEingangHeader HEADER = GrpcEingangHeaderTestFactory.create(); + public static final GrpcAntragsteller ANTRAGSTELLER = GrpcAntragstellerTestFactory.create(); + public static final GrpcFormData FORM_DATA = GrpcFormDataTestFactory.create(); + + public static GrpcEingangStub create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcEingangStub.newBuilder() + .setHeader(HEADER) + .setAntragsteller(ANTRAGSTELLER) + .setFormData(FORM_DATA); + } +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java new file mode 100644 index 000000000..b10b58cc0 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java @@ -0,0 +1,21 @@ +package de.ozgcloud.eingang.forwarder; + +import java.util.UUID; + +import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; +import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria.Builder; + +public class GrpcRouteCriteriaTestFactory { + + public static final String ORGANISATION_EINHEIT_ID = UUID.randomUUID().toString(); + + public static GrpcRouteCriteria create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcRouteCriteria.newBuilder() + .setOrganisationEinheitId(ORGANISATION_EINHEIT_ID); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java index ddd6a44d2..9df66980d 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java @@ -31,7 +31,7 @@ import de.ozgcloud.vorgang.vorgang.GrpcEingang; public class GrpcRouteForwardingRequestTestFactory { public static final GrpcEingang EINGANG = GrpcEingangTestFactory.create(); - public static final GrpcRouteCriteria CRITERIA = RouteCriteriaTestFactory.createGrpc(); + public static final GrpcRouteCriteria CRITERIA = GrpcRouteCriteriaTestFactory.create(); public static GrpcRouteForwardingRequest create() { return createBuilder().build(); diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java new file mode 100644 index 000000000..76192949b --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java @@ -0,0 +1,23 @@ +package de.ozgcloud.eingang.forwarder; + +import de.ozgcloud.eingang.forwarding.GrpcEingangStub; +import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding.Builder; + +public class GrpcRouteForwardingTestFactory { + + public static final GrpcRouteCriteria ROUTE_CRITERIA = GrpcRouteCriteriaTestFactory.create(); + public static final GrpcEingangStub EINGANG_STUB = GrpcEingangStubTestFactory.create(); + + public static GrpcRouteForwarding create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcRouteForwarding.newBuilder() + .setEingangStub(EINGANG_STUB) + .setRouteCriteria(ROUTE_CRITERIA); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java deleted file mode 100644 index 49c265a75..000000000 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2023 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.eingang.forwarder; - -import java.util.Optional; -import java.util.UUID; - -import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; - -public class RouteCriteriaTestFactory { - - public static final String ORGANISATION_EINHEIT_ID = UUID.randomUUID().toString(); - - public static RouteCriteria create() { - return createBuilder().build(); - } - - public static RouteCriteria.RouteCriteriaBuilder createBuilder() { - return RouteCriteria.builder() - .organisationEinheitId(Optional.of(ORGANISATION_EINHEIT_ID)); - } - - public static GrpcRouteCriteria createGrpc() { - return createGrpcBuilder().build(); - } - - public static GrpcRouteCriteria.Builder createGrpcBuilder() { - return GrpcRouteCriteria.newBuilder() - .setOrganisationseinheitenId(ORGANISATION_EINHEIT_ID); - } -} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java new file mode 100644 index 000000000..c3475b803 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java @@ -0,0 +1,101 @@ +package de.ozgcloud.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.router.GrpcAntragstellerTestFactory; +import de.ozgcloud.eingang.router.GrpcEingangHeaderTestFactory; +import de.ozgcloud.eingang.router.ServiceKontoMapper; +import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper; + +class RouteForwardingMapperTest { + + @InjectMocks + private RouteForwardingMapper mapper = Mappers.getMapper(RouteForwardingMapper.class); + + @Mock + private GrpcFormDataMapper grpcFormDataMapper; + @Mock + private ServiceKontoMapper serviceKontoMapper; + + @Nested + class TestToFormData { + + private final GrpcRouteForwarding routeForwarding = GrpcRouteForwardingTestFactory.create(); + + @BeforeEach + void mock() { + when(serviceKontoMapper.fromGrpc(any())).thenReturn(ServiceKontoTestFactory.create()); + when(grpcFormDataMapper.mapFromFormData(GrpcAntragstellerTestFactory.OTHER_DATA)).thenReturn(AntragstellerTestFactory.DATA); + when(grpcFormDataMapper.mapFromFormData(GrpcEingangStubTestFactory.FORM_DATA)).thenReturn(FormDataTestFactory.FORM_DATA); + } + + @Test + void shouldCallServiceKontoMapper() { + mapper.toFormData(routeForwarding); + + verify(serviceKontoMapper).fromGrpc(GrpcEingangHeaderTestFactory.SERVICE_KONTO); + } + + @Test + void shouldCallFormDataMapperWithAntragstellerData() { + mapper.toFormData(routeForwarding); + + verify(grpcFormDataMapper).mapFromFormData(GrpcAntragstellerTestFactory.OTHER_DATA); + } + + @Test + void shouldCallFormDataMapperWithFormData() { + mapper.toFormData(routeForwarding); + + verify(grpcFormDataMapper).mapFromFormData(GrpcEingangStubTestFactory.FORM_DATA); + } + + @Test + void shouldMapHeader() { + var formDataHeader = mapper.toFormData(routeForwarding).getHeader(); + + assertThat(formDataHeader).usingRecursiveComparison().isEqualTo(FormDataTestFactory.HEADER); + } + + @Test + void shouldMapAntragsteller() { + var expectedAntragSteller = AntragstellerTestFactory.createBuilder().firmaName(AntragstellerTestFactory.FIRMA_NAME).build(); + + var antragsteller = mapper.toFormData(routeForwarding).getAntragsteller(); + + assertThat(antragsteller).usingRecursiveComparison().isEqualTo(expectedAntragSteller); + } + + @Test + void shouldMapFormData() { + var formData = mapper.toFormData(routeForwarding).getFormData(); + + assertThat(formData).isSameAs(FormDataTestFactory.FORM_DATA); + } + + @Test + void shouldMapZustaendigeStelles() { + var expectedZustaendigeStelle = ZustaendigeStelle.builder() + .organisationseinheitenId(GrpcRouteCriteriaTestFactory.ORGANISATION_EINHEIT_ID) + .build(); + + var zustaendigeStelles = mapper.toFormData(routeForwarding).getZustaendigeStelles(); + + assertThat(zustaendigeStelles).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedZustaendigeStelle); + } + } +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java index e4c711fbc..f43db02d1 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java @@ -1,13 +1,6 @@ package de.ozgcloud.eingang.forwarder; -import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Optional; - import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; @@ -15,7 +8,6 @@ import org.mockito.Mock; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; -import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; import de.ozgcloud.eingang.router.VorgangService; class RouteForwardingServiceTest { @@ -32,35 +24,37 @@ class RouteForwardingServiceTest { private final FormData formData = FormDataTestFactory.create(); - @Test - void shouldCallVorgangService() { - var criteria = RouteCriteriaTestFactory.create(); + // @Test + // void shouldCallVorgangService() { + // var criteria = RouteCriteriaTestFactory.create(); - routeForwardingService.route(criteria, formData); + // routeForwardingService.route(criteria, formData); - verify(vorgangService).createVorgang(formDataCaptor.capture()); - assertThat(formDataCaptor.getValue()).usingRecursiveComparison().ignoringFields("zustaendigeStelles").isEqualTo(formData); - } + // verify(vorgangService).createVorgang(formDataCaptor.capture()); + // assertThat(formDataCaptor.getValue()).usingRecursiveComparison().ignoringFields("zustaendigeStelles").isEqualTo(formData); + // } - @Test - void shouldSetOrganisationEinheitIdInFormData() { - var criteria = RouteCriteriaTestFactory.create(); - var expectedZustaendigeStelle = ZustaendigeStelle.builder() - .organisationseinheitenId(RouteCriteriaTestFactory.ORGANISATION_EINHEIT_ID) - .build(); + // @Test + // void shouldSetOrganisationEinheitIdInFormData() { + // var criteria = RouteCriteriaTestFactory.create(); + // var expectedZustaendigeStelle = ZustaendigeStelle.builder() + // .organisationseinheitenId(RouteCriteriaTestFactory.ORGANISATION_EINHEIT_ID) + // .build(); - routeForwardingService.route(criteria, formData); + // routeForwardingService.route(criteria, formData); - verify(vorgangService).createVorgang(formDataCaptor.capture()); - assertThat(formDataCaptor.getValue().getZustaendigeStelles()).usingRecursiveFieldByFieldElementComparator() - .containsExactly(expectedZustaendigeStelle); - } + // verify(vorgangService).createVorgang(formDataCaptor.capture()); + // assertThat(formDataCaptor.getValue().getZustaendigeStelles()).usingRecursiveFieldByFieldElementComparator() + // .containsExactly(expectedZustaendigeStelle); + // } - @Test - void shouldThrowUnsupportedOperationException() { - var criteria = RouteCriteriaTestFactory.createBuilder().organisationEinheitId(Optional.empty()).build(); + // @Test + // void shouldThrowUnsupportedOperationException() { + // var criteria = + // RouteCriteriaTestFactory.createBuilder().organisationEinheitId(Optional.empty()).build(); - assertThrows(UnsupportedOperationException.class, () -> routeForwardingService.route(criteria, formData)); - } + // assertThrows(UnsupportedOperationException.class, () -> + // routeForwardingService.route(criteria, formData)); + // } } } diff --git a/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java b/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java index 85b8a1685..97aed9ca4 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/ServiceKontoMapper.java @@ -48,7 +48,7 @@ import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, // uses = { GrpcObjectMapper.class }) -abstract class ServiceKontoMapper { +public abstract class ServiceKontoMapper { static final String DEFAULT_TRUST_LEVEL = "STORK-QAA-Level-1"; @@ -71,7 +71,7 @@ abstract class ServiceKontoMapper { @Mapping(target = "postfachAddresses", source = "postfachAddressesList") @Mapping(target = "trustLevel", source = "trustLevel", qualifiedByName = "mapTrustLevel") @Mapping(target = "postfachAddress", ignore = true) - abstract ServiceKonto fromGrpc(GrpcServiceKonto serviceKonto); + public abstract ServiceKonto fromGrpc(GrpcServiceKonto serviceKonto); PostfachAddressIdentifier mapToIdentifier(GrpcObject identifier) { var stringIdentifier = MapUtils.getString(grpcObjectMapper.mapFromGrpc(identifier), StringBasedIdentifier.POSTFACH_ID_FIELD); -- GitLab From 04cd6e35f5fcff5adffc98a75cefbf3ff568b174 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 15:07:05 +0100 Subject: [PATCH 15/28] OZG-7573 license header and clean up --- eingang-manager-interface/pom.xml | 2 +- .../src/main/protobuf/forward.model.proto | 2 +- .../src/main/protobuf/forward.proto | 2 +- .../EingangStubReceiverStreamObserver.java | 23 +++++ .../eingang/forwarder/FileService.java | 23 +++++ .../forwarder/IncomingFileGroupMapper.java | 23 +++++ .../eingang/forwarder/IncomingFileMapper.java | 23 +++++ .../forwarder/RouteForwardingMapper.java | 2 +- .../GrpcAntragstellerTestFactory.java | 2 +- .../GrpcAttachmentFileTestFactory.java | 23 +++++ .../forwarder/GrpcEingangStubTestFactory.java | 24 +++++- .../GrpcRepresentationFileTestFactory.java | 23 +++++ .../GrpcRouteCriteriaTestFactory.java | 23 +++++ ...GrpcRouteForwardingRequestTestFactory.java | 43 ---------- .../GrpcRouteForwardingTestFactory.java | 23 +++++ .../IncomingFileGroupMapperTest.java | 23 +++++ .../forwarder/IncomingFileMapperTest.java | 23 +++++ .../forwarder/RouteForwardingMapperTest.java | 24 +++++- .../forwarder/RouteForwardingServiceTest.java | 23 +++++ router/pom.xml | 11 --- .../eingang/router/GrpcEingangMapper.java | 13 --- .../eingang/router/GrpcEingangMapperTest.java | 84 ------------------- .../router/GrpcEingangTestFactory.java | 57 ------------- .../GrpcPostfachAddressTestFactory.java | 23 +++++ .../router/GrpcServiceKontoTestFactory.java | 23 +++++ .../GrpcZustaendigeStelleTestFactory.java | 57 ------------- 26 files changed, 350 insertions(+), 272 deletions(-) rename {router/src/test/java/de/ozgcloud/eingang/router => forwarder/src/test/java/de/ozgcloud/eingang/forwarder}/GrpcAntragstellerTestFactory.java (98%) delete mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java delete mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java delete mode 100644 router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java diff --git a/eingang-manager-interface/pom.xml b/eingang-manager-interface/pom.xml index 2aa828f6c..b877903e6 100644 --- a/eingang-manager-interface/pom.xml +++ b/eingang-manager-interface/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den + Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den Ministerpräsidenten des Landes Schleswig-Holstein Staatskanzlei Abteilung Digitalisierung und zentrales IT-Management der Landesregierung diff --git a/eingang-manager-interface/src/main/protobuf/forward.model.proto b/eingang-manager-interface/src/main/protobuf/forward.model.proto index 5b0c4a989..29076e289 100644 --- a/eingang-manager-interface/src/main/protobuf/forward.model.proto +++ b/eingang-manager-interface/src/main/protobuf/forward.model.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung diff --git a/eingang-manager-interface/src/main/protobuf/forward.proto b/eingang-manager-interface/src/main/protobuf/forward.proto index 6d6085eba..ef695a3e8 100644 --- a/eingang-manager-interface/src/main/protobuf/forward.proto +++ b/eingang-manager-interface/src/main/protobuf/forward.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 8f6381157..5c9f3d4ad 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import java.io.File; diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java index 812748eb1..862aba7b8 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import java.io.File; diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java index 024d2c03e..ba1939b21 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import java.util.List; diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java index 26e3ceddd..40176db71 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import org.mapstruct.Mapper; diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java index 5d519d5c9..3665e7f6c 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAntragstellerTestFactory.java similarity index 98% rename from router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java rename to forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAntragstellerTestFactory.java index 61893f6a7..c125f8865 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcAntragstellerTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAntragstellerTestFactory.java @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.eingang.router; +package de.ozgcloud.eingang.forwarder; import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java index 431f4e0db..12382dcfe 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import com.thedeanda.lorem.LoremIpsum; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java index ac07fe28f..f1fc1c664 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java @@ -1,8 +1,30 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import de.ozgcloud.eingang.forwarding.GrpcEingangStub; import de.ozgcloud.eingang.forwarding.GrpcEingangStub.Builder; -import de.ozgcloud.eingang.router.GrpcAntragstellerTestFactory; import de.ozgcloud.eingang.router.GrpcEingangHeaderTestFactory; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory; import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java index ce7fb5406..e5155199a 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java index b10b58cc0..450f68612 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import java.util.UUID; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java deleted file mode 100644 index 9df66980d..000000000 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2023 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.eingang.forwarder; - -import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; -import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; -import de.ozgcloud.eingang.router.GrpcEingangTestFactory; -import de.ozgcloud.vorgang.vorgang.GrpcEingang; - -public class GrpcRouteForwardingRequestTestFactory { - - public static final GrpcEingang EINGANG = GrpcEingangTestFactory.create(); - public static final GrpcRouteCriteria CRITERIA = GrpcRouteCriteriaTestFactory.create(); - - public static GrpcRouteForwardingRequest create() { - return createBuilder().build(); - } - - public static GrpcRouteForwardingRequest.Builder createBuilder() { - return GrpcRouteForwardingRequest.newBuilder(); - } -} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java index 76192949b..ca29d219b 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import de.ozgcloud.eingang.forwarding.GrpcEingangStub; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java index acdc39b91..b86144b64 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import static org.assertj.core.api.Assertions.*; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java index 940332b66..c8b12b9f1 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import static org.assertj.core.api.Assertions.*; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java index c3475b803..406c6e1bd 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import static org.assertj.core.api.Assertions.*; @@ -16,7 +39,6 @@ import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; -import de.ozgcloud.eingang.router.GrpcAntragstellerTestFactory; import de.ozgcloud.eingang.router.GrpcEingangHeaderTestFactory; import de.ozgcloud.eingang.router.ServiceKontoMapper; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java index f43db02d1..45015dff9 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import org.junit.jupiter.api.Nested; diff --git a/router/pom.xml b/router/pom.xml index 95e980d63..f0659ace4 100644 --- a/router/pom.xml +++ b/router/pom.xml @@ -73,11 +73,6 @@ <artifactId>commons-lang3</artifactId> </dependency> - <dependency> - <groupId>org.mapstruct</groupId> - <artifactId>mapstruct</artifactId> - </dependency> - <!-- Dev --> <dependency> <groupId>org.projectlombok</groupId> @@ -97,12 +92,6 @@ <type>test-jar</type> <scope>test</scope> </dependency> - <dependency> - <groupId>de.ozgcloud.vorgang</groupId> - <artifactId>vorgang-manager-utils</artifactId> - <type>test-jar</type> - <scope>test</scope> - </dependency> </dependencies> <build> diff --git a/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java b/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java index 382c59752..b5fd75f9a 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java @@ -82,17 +82,4 @@ public interface GrpcEingangMapper { default String uuidToString(UUID id) { return id.toString(); } - - @Mapping(target = "attachment", ignore = true) - @Mapping(target = "representation", ignore = true) - @Mapping(target = "zustaendigeStelles", ignore = true) - @Mapping(target = "control", ignore = true) - @Mapping(target = "attachments", source = "attachmentsList") - @Mapping(target = "representations", source = "representationsList") - @Mapping(target = "antragsteller.data", source = "antragsteller.otherData") - FormData toFormData(GrpcEingang eingang); - - @Mapping(target = "files", source = "filesList") - @Mapping(target = "file", ignore = true) - IncomingFileGroup mapFileGroupFromGrpc(GrpcIncomingFileGroup fileGroup); } diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java index a262e8c7a..eed08a895 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java @@ -40,7 +40,6 @@ import org.mockito.Mock; import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; -import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelleTestFactory; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper; import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; @@ -198,87 +197,4 @@ class GrpcEingangMapperTest { return mapper.toEingang(FormDataTestFactory.create(), Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)); } } - - @Nested - class TestToFormData { - - private final GrpcEingang eingang = GrpcEingangTestFactory.create(); - - @BeforeEach - void mock() { - when(serviceKontoMapper.fromGrpc(any())).thenReturn(ServiceKontoTestFactory.create()); - when(grpcFormDataMapper.mapFromFormData(GrpcAntragstellerTestFactory.OTHER_DATA)).thenReturn(AntragstellerTestFactory.DATA); - when(grpcFormDataMapper.mapFromFormData(GrpcEingangTestFactory.FORM_DATA)).thenReturn(FormDataTestFactory.FORM_DATA); - } - - @Test - void shouldCallServiceKontoMapper() { - mapper.toFormData(eingang); - - verify(serviceKontoMapper).fromGrpc(GrpcEingangHeaderTestFactory.SERVICE_KONTO); - } - - @Test - void shouldCallFormDataMapperWithAntragstellerData() { - mapper.toFormData(eingang); - - verify(grpcFormDataMapper).mapFromFormData(GrpcAntragstellerTestFactory.OTHER_DATA); - } - - @Test - void shouldCallFormDataMapperWithFormData() { - mapper.toFormData(eingang); - - verify(grpcFormDataMapper).mapFromFormData(GrpcEingangTestFactory.FORM_DATA); - } - - @Test - void shouldMapToFormData() { - var expectedFormData = FormDataTestFactory.createBuilder() - .numberOfAttachments(GrpcEingangTestFactory.NUMBER_OF_ATTACHMENTS) - .numberOfRepresentations(GrpcEingangTestFactory.NUMBER_OF_REPRESENTATIONS) - .build(); - - var formData = mapper.toFormData(eingang); - - assertThat(formData).usingRecursiveComparison() - .ignoringFields("antragsteller.firmaName", "control", "attachments", "representations", "zustaendigeStelles") - .isEqualTo(expectedFormData); - } - - @Nested - class TestZustaendigestelles { - - @Test - void shouldMapZustaendigeStelles() { - var zustaendigeStelles = mapper.toFormData(eingang).getZustaendigeStelles(); - - assertThat(zustaendigeStelles).usingRecursiveFieldByFieldElementComparator().containsExactly(ZustaendigeStelleTestFactory.create()); - } - } - - @Nested - class TestAttachments { - - @Test - void shouldMapAttachments() { - var attachments = mapper.toFormData(eingang).getAttachments(); - - assertThat(attachments).usingRecursiveFieldByFieldElementComparatorIgnoringFields("files.file") - .containsExactly(FormDataTestFactory.ATTACHMENTS.get(0)); - } - } - - @Nested - class TestRepresentations { - - @Test - void shouldMapRepresentations() { - var representations = mapper.toFormData(eingang).getRepresentations(); - - assertThat(representations).usingRecursiveFieldByFieldElementComparatorIgnoringFields("file") - .containsExactly(FormDataTestFactory.REPRESENTATIONS.get(0)); - } - } - } } \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java deleted file mode 100644 index 8e15b541a..000000000 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangTestFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2025 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.eingang.router; - -import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; -import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory; -import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory; -import de.ozgcloud.vorgang.vorgang.GrpcEingang; -import de.ozgcloud.vorgang.vorgang.GrpcFormData; -import de.ozgcloud.vorgang.vorgang.GrpcSubForm; - -public class GrpcEingangTestFactory { - - public static final GrpcFormData FORM_DATA = GrpcFormDataTestFactory.create(); - public static final int NUMBER_OF_REPRESENTATIONS = 5; - public static final int NUMBER_OF_ATTACHMENTS = 4; - public static final String ID = FormDataTestFactory.ID; - public static final GrpcSubForm SUB_FORM = GrpcSubFormTestFactory.create(); - - public static GrpcEingang create() { - return createBuilder().build(); - } - - public static GrpcEingang.Builder createBuilder() { - return GrpcEingang.newBuilder() - .setId(ID) - .setHeader(GrpcEingangHeaderTestFactory.create()) - .setAntragsteller(GrpcAntragstellerTestFactory.create()) - .setZustaendigeStelle(GrpcZustaendigeStelleTestFactory.create()) - .setFormData(FORM_DATA) - .addAttachments(GrpcIncomingFileGroupTestFactory.create()) - .setNumberOfAttachments(NUMBER_OF_ATTACHMENTS) - .addRepresentations(GrpcIncomingFileTestFactory.create()) - .setNumberOfRepresentations(NUMBER_OF_REPRESENTATIONS); - } -} \ No newline at end of file diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java index f8ba6cd4b..902a463e9 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.router; import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java index 1995e8123..d223b64c5 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.router; import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; diff --git a/router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java deleted file mode 100644 index d96403837..000000000 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcZustaendigeStelleTestFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2023 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.eingang.router; - -import de.ozgcloud.eingang.common.formdata.ZustaendigeStelleTestFactory; -import de.ozgcloud.vorgang.vorgang.GrpcZustaendigeStelle; - -public class GrpcZustaendigeStelleTestFactory { - - public static final String ORGANISATIONSEINHEIT_ID = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID; - public static final String EMAIL = ZustaendigeStelleTestFactory.EMAIL; - public static final String GEMEINDE_SCHLUESSEL = ZustaendigeStelleTestFactory.GEMEINDE_SCHLUESSEL; - public static final String AMTLICHER_REGIONAL_SCHLUESSEL = ZustaendigeStelleTestFactory.AMTLICHER_REGIONAL_SCHLUESSEL; - public static final String HAUSANSCHRIFT_STRASSE = ZustaendigeStelleTestFactory.HAUSANSCHRIFT_STRASSE; - public static final String HAUSANSCHRIFT_PLZ = ZustaendigeStelleTestFactory.HAUSANSCHRIFT_PLZ; - public static final String HAUSANSCHRIFT_ORT = ZustaendigeStelleTestFactory.HAUSANSCHRIFT_ORT; - public static final String TELEFON = ZustaendigeStelleTestFactory.TELEFON; - public static final String BEZEICHNUNG = ZustaendigeStelleTestFactory.BEZEICHNUNG; - - public static GrpcZustaendigeStelle create() { - return createBuilder().build(); - } - - public static GrpcZustaendigeStelle.Builder createBuilder() { - return GrpcZustaendigeStelle.newBuilder() - .setOrganisationseinheitenId(ORGANISATIONSEINHEIT_ID) - .setEmail(EMAIL) - .setBezeichnung(BEZEICHNUNG) - .setGemeindeSchluessel(GEMEINDE_SCHLUESSEL) - .setAmtlicherRegionalSchluessel(AMTLICHER_REGIONAL_SCHLUESSEL) - .setHausanschriftStrasse(HAUSANSCHRIFT_STRASSE) - .setHausanschriftPlz(HAUSANSCHRIFT_PLZ) - .setHausanschriftOrt(HAUSANSCHRIFT_ORT) - .setTelefon(TELEFON); - } -} \ No newline at end of file -- GitLab From a6ec45afca20e5bcc03b0bb198c05a928f0f2660 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 15:32:57 +0100 Subject: [PATCH 16/28] OZG-7573 implement FileService --- .../eingang/forwarder/FileService.java | 5 ++- .../eingang/forwarder/FileServiceTest.java | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java index 862aba7b8..91dcc0d3e 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java @@ -30,13 +30,14 @@ import java.util.concurrent.CompletableFuture; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import de.ozgcloud.common.binaryfile.TempFileUtils; + @Service class FileService { @Async public CompletableFuture<File> saveToFile(InputStream inputStream) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'saveToFile'"); + return CompletableFuture.completedFuture(TempFileUtils.writeTmpFile(inputStream)); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java new file mode 100644 index 000000000..795bcf585 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java @@ -0,0 +1,39 @@ +package de.ozgcloud.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; + +import java.io.ByteArrayInputStream; +import java.nio.file.Files; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Spy; + +import com.thedeanda.lorem.LoremIpsum; + +import lombok.SneakyThrows; + +class FileServiceTest { + + @Spy + private FileService service; + + @Nested + class TestSaveToFile { + + private final byte[] content = LoremIpsum.getInstance().getWords(100).getBytes(); + + @Test + @SneakyThrows + void shouldReturnFutureOfFile() { + try (var inputStream = new ByteArrayInputStream(content);) { + var fileFuture = service.saveToFile(inputStream); + + var fileContent = Files.readAllBytes(fileFuture.get().toPath()); + assertThat(fileContent).isEqualTo(content); + + } + } + + } +} -- GitLab From 32022c5ca1fb42087449f7bb6f72a3544343cc7b Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Mon, 17 Mar 2025 15:36:29 +0100 Subject: [PATCH 17/28] OZG-7573 implement RouteForwardingService --- .../forwarder/RouteForwardingService.java | 14 +----- .../forwarder/RouteForwardingServiceTest.java | 43 ++++--------------- 2 files changed, 9 insertions(+), 48 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java index 8a455d31e..40e9b7707 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingService.java @@ -35,19 +35,7 @@ class RouteForwardingService { private final VorgangService vorgangService; - // public void route(RouteCriteria criteria, FormData formData) { - // vorgangService.createVorgang(formData.toBuilder() - // .clearZustaendigeStelles() - // .zustaendigeStelle(ZustaendigeStelle.builder() - // .organisationseinheitenId(criteria.getOrganisationEinheitId() - // .orElseThrow(() -> new UnsupportedOperationException("OrganisationseinheitId - // is required!"))) - // .build()) - // .build()); - // } - public void route(FormData formData) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'route'"); + vorgangService.createVorgang(formData); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java index 45015dff9..4b36715c7 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java @@ -23,9 +23,10 @@ */ package de.ozgcloud.eingang.forwarder; +import static org.mockito.Mockito.*; + import org.junit.jupiter.api.Nested; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; +import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -39,45 +40,17 @@ class RouteForwardingServiceTest { private RouteForwardingService routeForwardingService; @Mock private VorgangService vorgangService; - @Captor - private ArgumentCaptor<FormData> formDataCaptor; @Nested class TestRoute { private final FormData formData = FormDataTestFactory.create(); - // @Test - // void shouldCallVorgangService() { - // var criteria = RouteCriteriaTestFactory.create(); - - // routeForwardingService.route(criteria, formData); - - // verify(vorgangService).createVorgang(formDataCaptor.capture()); - // assertThat(formDataCaptor.getValue()).usingRecursiveComparison().ignoringFields("zustaendigeStelles").isEqualTo(formData); - // } - - // @Test - // void shouldSetOrganisationEinheitIdInFormData() { - // var criteria = RouteCriteriaTestFactory.create(); - // var expectedZustaendigeStelle = ZustaendigeStelle.builder() - // .organisationseinheitenId(RouteCriteriaTestFactory.ORGANISATION_EINHEIT_ID) - // .build(); - - // routeForwardingService.route(criteria, formData); - - // verify(vorgangService).createVorgang(formDataCaptor.capture()); - // assertThat(formDataCaptor.getValue().getZustaendigeStelles()).usingRecursiveFieldByFieldElementComparator() - // .containsExactly(expectedZustaendigeStelle); - // } - - // @Test - // void shouldThrowUnsupportedOperationException() { - // var criteria = - // RouteCriteriaTestFactory.createBuilder().organisationEinheitId(Optional.empty()).build(); + @Test + void shouldCallVorgangService() { + routeForwardingService.route(formData); - // assertThrows(UnsupportedOperationException.class, () -> - // routeForwardingService.route(criteria, formData)); - // } + verify(vorgangService).createVorgang(formData); + } } } -- GitLab From e4c206f68c9a979fc03375730e21a65d55d4d88b Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Tue, 18 Mar 2025 11:43:46 +0100 Subject: [PATCH 18/28] OZG-7573 implement EingangStubReceiverStreamObserver --- .../EingangStubReceiverStreamObserver.java | 36 +- ...EingangStubReceiverStreamObserverTest.java | 1024 +++++++++++++++++ .../GrpcAttachmentFileTestFactory.java | 5 +- .../forwarder/GrpcAttachmentTestFactory.java | 47 + .../forwarder/GrpcFileContentTestFactory.java | 47 + .../GrpcRepresentationTestFactory.java | 46 + ...GrpcRouteForwardingRequestTestFactory.java | 54 + 7 files changed, 1240 insertions(+), 19 deletions(-) create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcFileContentTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationTestFactory.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 5c9f3d4ad..d5f1aa22a 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -103,14 +103,14 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } } - private void handleRouteForwarding(GrpcRouteForwarding routeForwarding) { + void handleRouteForwarding(GrpcRouteForwarding routeForwarding) { if (Objects.nonNull(formData)) { throw new IllegalStateException("Received second RouteForwarding. Send only one per request."); } formData = routeForwardingMapper.toFormData(routeForwarding); } - private void handleAttachment(GrpcAttachment attachment) { + void handleAttachment(GrpcAttachment attachment) { if (attachment.hasFile()) { setCurrentMetadata(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); groupName = Optional.of(attachment.getFile().getGroupName()); @@ -119,7 +119,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } } - private void handleRepresentation(GrpcRepresentation representation) { + void handleRepresentation(GrpcRepresentation representation) { if (representation.hasFile()) { setCurrentMetadata(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); } else { @@ -128,21 +128,21 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } - private void setCurrentMetadata(IncomingFile metaData) { + void setCurrentMetadata(IncomingFile metaData) { if (Objects.nonNull(currentFile)) { - throw new TechnicalException("Received additional file before previos file reached the end."); + throw new IllegalStateException("Received additional file before previos file reached the end."); } currentFile = metaData; } - private void handleFileContent(GrpcFileContent fileContent) { + void handleFileContent(GrpcFileContent fileContent) { if (Objects.isNull(receivingFileContent)) { initContentReceiving(); } storeFileContent(fileContent); } - private void initContentReceiving() { + void initContentReceiving() { try { pipedInput = new PipedInputStream(CHUNK_SIZE); pipedOutput = new PipedOutputStream(pipedInput); @@ -152,9 +152,9 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } } - private void storeFileContent(GrpcFileContent content) { + void storeFileContent(GrpcFileContent content) { if (Objects.isNull(currentFile)) { - throw new TechnicalException("File content received before metadata."); + throw new IllegalStateException("File content received before metadata."); } try { pipedOutput.write(content.getContent().toByteArray()); @@ -166,14 +166,16 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } } - private void handleEndOfFile() { + void handleEndOfFile() { closeOutputPipe(); var completedIncomingFile = currentFile.toBuilder().file(getSavedFileContent()).build(); - groupName.map(group -> attachments.get(group)).orElse(representations).add(completedIncomingFile); + groupName.map(group -> attachments.computeIfAbsent(group, s -> new ArrayList<IncomingFile>())) + .orElse(representations) + .add(completedIncomingFile); resetFileReceiving(); } - private File getSavedFileContent() { + File getSavedFileContent() { try { return receivingFileContent.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); } catch (ExecutionException | TimeoutException e) { @@ -186,7 +188,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } } - private void resetFileReceiving() { + void resetFileReceiving() { currentFile = null; groupName = Optional.empty(); pipedOutput = null; @@ -201,11 +203,11 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou closeInputPipe(); } - private void closeOutputPipe() { + void closeOutputPipe() { IOUtils.closeQuietly(pipedOutput, e -> LOG.error("Cannot close output stream.", e)); } - private void closeInputPipe() { + void closeInputPipe() { IOUtils.closeQuietly(pipedInput, e -> LOG.error("Cannot close input stream.", e)); } @@ -215,13 +217,15 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou responseConsumer.accept(GrpcRouteForwardingResponse.getDefaultInstance()); } - private FormData assembleFormData() { + FormData assembleFormData() { if (Objects.isNull(formData)) { throw new IllegalStateException("Never received RouteForwarding containing EingangStub and RouteCriteria."); } return formData.toBuilder() .representations(representations) .attachments(attachments.entrySet().stream().map(incomingFileGroupMapper::fromMapEntry).toList()) + .numberOfAttachments(attachments.size()) + .numberOfRepresentations(representations.size()) .build(); } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java new file mode 100644 index 000000000..f4bacd0b2 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -0,0 +1,1024 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.test.util.ReflectionTestUtils; + +import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.forwarding.GrpcAttachment; +import de.ozgcloud.eingang.forwarding.GrpcFileContent; +import de.ozgcloud.eingang.forwarding.GrpcRepresentation; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; +import lombok.SneakyThrows; + +class EingangStubReceiverStreamObserverTest { + + private EingangStubReceiverStreamObserver observer; + + @Mock + private RouteForwardingMapper routeForwardingMapper; + @Mock + private IncomingFileMapper incomingFileMapper; + @Mock + private IncomingFileGroupMapper incomingFileGroupMapper; + @Mock + private Function<InputStream, CompletableFuture<File>> fileSaver; + @Mock + private Consumer<FormData> formDataConsumer; + @Mock + private Consumer<GrpcRouteForwardingResponse> responseConsumer; + + @BeforeEach + void setUp() { + observer = spy(EingangStubReceiverStreamObserver.builder() + .fileSaver(fileSaver) + .routeForwardingMapper(routeForwardingMapper) + .incomingFileMapper(incomingFileMapper) + .incomingFileGroupMapper(incomingFileGroupMapper) + .formDataConsumer(formDataConsumer) + .responseConsumer(responseConsumer) + .build()); + } + + @Nested + class TestOnNext { + + @Nested + class TestOnRouteForwarding { + + @BeforeEach + void mock() { + doNothing().when(observer).handleRouteForwarding(any()); + } + + @Test + void shouldCallHandleRouteForwarding() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithRouteForwarding()); + + verify(observer).handleRouteForwarding(GrpcRouteForwardingRequestTestFactory.ROUTE_FORWARDING); + } + + @Test + void shouldNotCallHandleAttachment() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithRouteForwarding()); + + verify(observer, never()).handleAttachment(any()); + } + + @Test + void shouldNotCallHandleRepresentation() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithRouteForwarding()); + + verify(observer, never()).handleRepresentation(any()); + } + } + + @Nested + class TestOnAttachment { + @Test + void shouldCallHandleAttachment() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithAttachment()); + + verify(observer).handleAttachment(GrpcRouteForwardingRequestTestFactory.ATTACHMENT); + } + + @Test + void shouldNotCallHandleRouteForwarding() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithAttachment()); + + verify(observer, never()).handleRouteForwarding(any()); + } + + @Test + void shouldNotCallHandleRepresentation() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithAttachment()); + + verify(observer, never()).handleRepresentation(any()); + } + } + + @Nested + class TestOnRepresentation { + @Test + void shouldCallHandleRepresentation() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithRepresentation()); + + verify(observer).handleRepresentation(GrpcRouteForwardingRequestTestFactory.REPRESENTATION); + } + + @Test + void shouldNotCallHandleRouteForwarding() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithRepresentation()); + + verify(observer, never()).handleRouteForwarding(any()); + } + + @Test + void shouldNotCallHandleAttachment() { + observer.onNext(GrpcRouteForwardingRequestTestFactory.createWithRepresentation()); + + verify(observer, never()).handleAttachment(any()); + } + } + } + + @Nested + class TestHandleRouteForwarding { + + private final GrpcRouteForwarding routeForwarding = GrpcRouteForwardingTestFactory.create(); + + @Test + void shouldThrowIllegalStateExceptionIfFormDataIsSet() { + setFormData(FormDataTestFactory.create()); + + assertThrows(IllegalStateException.class, () -> observer.handleRouteForwarding(routeForwarding)); + + } + + @Test + void shouldMapRouteForwarding() { + observer.handleRouteForwarding(routeForwarding); + + verify(routeForwardingMapper).toFormData(routeForwarding); + } + + @Test + void shouldSetFormData() { + var formData = FormDataTestFactory.create(); + when(routeForwardingMapper.toFormData(any())).thenReturn(formData); + + observer.handleRouteForwarding(routeForwarding); + + assertThat(getFormData()).isEqualTo(formData); + } + } + + @Nested + class TestHandleAttachment { + + @Nested + class TestWithFile { + + private final GrpcAttachment attachmentWithFile = GrpcAttachmentTestFactory.createWithFile(); + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void mock() { + doNothing().when(observer).setCurrentMetadata(any()); + when(incomingFileMapper.fromGrpcAttachmentFile(any())).thenReturn(incomingFile); + } + + @Test + void shouldCallIncomingFileMapper() { + observer.handleAttachment(attachmentWithFile); + + verify(incomingFileMapper).fromGrpcAttachmentFile(GrpcAttachmentTestFactory.FILE); + } + + @Test + void shouldCallSetCurrentMetadata() { + observer.handleAttachment(attachmentWithFile); + + verify(observer).setCurrentMetadata(incomingFile); + } + + @Test + void shouldSetGroupName() { + observer.handleAttachment(attachmentWithFile); + + assertThat(getGroupName()).contains(GrpcAttachmentFileTestFactory.GROUP_NAME); + } + + @Test + void shouldNotCallHandleFileContent() { + observer.handleAttachment(attachmentWithFile); + + verify(observer, never()).handleFileContent(any()); + } + } + + @Nested + class TestWithContent { + + private final GrpcAttachment attachmentWithContent = GrpcAttachmentTestFactory.createWithContent(); + + @BeforeEach + void mock() { + doNothing().when(observer).handleFileContent(any()); + } + + @Test + void shouldCallHandleFileContent() { + observer.handleAttachment(attachmentWithContent); + + verify(observer).handleFileContent(GrpcAttachmentTestFactory.CONTENT); + } + + @Test + void shouldNotCallIncomingFileMapper() { + observer.handleAttachment(attachmentWithContent); + + verify(incomingFileMapper, never()).fromGrpcAttachmentFile(any()); + } + + @Test + void shouldNotSetGroupName() { + observer.handleAttachment(attachmentWithContent); + + assertThat(getGroupName()).isEmpty(); + } + } + } + + @Nested + class TestHandleRepresentation { + + @Nested + class TestWithFile { + + private final GrpcRepresentation representationWithFile = GrpcRepresentationTestFactory.createWithFile(); + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void mock() { + doNothing().when(observer).setCurrentMetadata(any()); + when(incomingFileMapper.fromGrpcRepresentationFile(any())).thenReturn(incomingFile); + } + + @Test + void shouldCallIncomingFileMapper() { + observer.handleRepresentation(representationWithFile); + + verify(incomingFileMapper).fromGrpcRepresentationFile(GrpcRepresentationTestFactory.FILE); + } + + @Test + void shouldCallSetCurrentMetadata() { + observer.handleRepresentation(representationWithFile); + + verify(observer).setCurrentMetadata(incomingFile); + } + + @Test + void shouldNotCallHandleFileContent() { + observer.handleRepresentation(representationWithFile); + + verify(observer, never()).handleFileContent(any()); + } + } + + @Nested + class TestWithContent { + + private final GrpcRepresentation representationWithContent = GrpcRepresentationTestFactory.createWithContent(); + + @BeforeEach + void mock() { + doNothing().when(observer).handleFileContent(any()); + } + + @Test + void shouldCallHandleFileContent() { + observer.handleRepresentation(representationWithContent); + + verify(observer).handleFileContent(GrpcRepresentationTestFactory.CONTENT); + } + + @Test + void shouldNotCallIncomingFileMapper() { + observer.handleRepresentation(representationWithContent); + + verify(incomingFileMapper, never()).fromGrpcRepresentationFile(any()); + } + } + } + + @Nested + class TestSetCurrentMetadata { + + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @Test + void shouldThrowIllegalStateExceptionIfCurrentFileIsSet() { + setCurrentFile(incomingFile); + + assertThrows(IllegalStateException.class, () -> observer.setCurrentMetadata(incomingFile)); + } + + @Test + void shouldSetCurrentFile() { + observer.setCurrentMetadata(incomingFile); + + assertThat(getCurrentFile()).isSameAs(incomingFile); + } + } + + @Nested + class TestHandleFileContent { + + private final GrpcFileContent fileContent = GrpcFileContentTestFactory.create(); + + @Nested + class TestOnReceivingFileContentIsNull { + @BeforeEach + void mock() { + doNothing().when(observer).initContentReceiving(); + doNothing().when(observer).storeFileContent(any()); + } + + @Test + void shouldCallInitContentReceiving() { + observer.handleFileContent(fileContent); + + verify(observer).initContentReceiving(); + } + + @Test + void shouldCallStoreFileContent() { + observer.handleFileContent(fileContent); + + verify(observer).storeFileContent(fileContent); + } + } + + @Nested + class TestOnReceivingFileContentIsNotNull { + @Mock + private CompletableFuture<File> receivingFileContent; + + @BeforeEach + void mock() { + doNothing().when(observer).storeFileContent(any()); + setFileContent(receivingFileContent); + } + + @Test + void shouldNotCallInitContentReceiving() { + observer.handleFileContent(fileContent); + + verify(observer, never()).initContentReceiving(); + } + + @Test + void shouldCallStoreFileContent() { + observer.handleFileContent(fileContent); + + verify(observer).storeFileContent(fileContent); + } + } + } + + @Nested + class TestInitContentReceiving { + + private final byte[] content = new byte[] { 1, 2, 3 }; + + @Test + void shouldCreateInputStream() { + observer.initContentReceiving(); + + assertThat(getPipedInput()).isNotNull(); + } + + @Test + void shouldCreateOutputStream() { + observer.initContentReceiving(); + + assertThat(getPipedOutput()).isNotNull(); + } + + @Test + void shouldCreateConnectedStreams() { + observer.initContentReceiving(); + + verifyStreamSetUp(); + } + + @SneakyThrows + private void verifyStreamSetUp() { + var pipedInput = getPipedInput(); + var pipedOutput = getPipedOutput(); + pipedOutput.write(content); + pipedOutput.close(); + var readBytes = pipedInput.readAllBytes(); + assertThat(readBytes).isEqualTo(content); + } + + @Test + void shouldCallFileSaver() { + observer.initContentReceiving(); + + verify(fileSaver).apply(getPipedInput()); + } + + @Test + void shouldSetReceivingFileContent() { + var fileFuture = CompletableFuture.completedFuture(mock(File.class)); + when(fileSaver.apply(any())).thenReturn(fileFuture); + + observer.initContentReceiving(); + + assertThat(getFileContent()).isSameAs(fileFuture); + } + } + + @Nested + class TestStoreFileContent { + @Mock + private PipedOutputStream pipedOutput; + + @BeforeEach + void setUp() { + setPipedOutput(pipedOutput); + } + + @Nested + class TestOnCurrentFileIsNull { + + @Test + void shouldThrowTechnicalException() { + var fileContent = GrpcFileContentTestFactory.create(); + + assertThrows(IllegalStateException.class, () -> observer.storeFileContent(fileContent)); + } + } + + @Nested + class TestOnCurrentFileIsNotNull { + + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void mock() { + setCurrentFile(incomingFile); + } + + @Test + @SneakyThrows + void shouldWriteContentToOutputStream() { + observer.storeFileContent(GrpcFileContentTestFactory.create()); + + verify(pipedOutput).write(GrpcFileContentTestFactory.CONTENT); + } + + @Test + void shouldCallHandleEndOfFile() { + doNothing().when(observer).handleEndOfFile(); + var fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(true).build(); + + observer.storeFileContent(fileContent); + + verify(observer).handleEndOfFile(); + } + + @Test + void shouldNotCallHandleEndOfFile() { + var fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(false).build(); + + observer.storeFileContent(fileContent); + + verify(observer, never()).handleEndOfFile(); + } + + @Test + @SneakyThrows + void shouldThrowTechnicalExceptionOnIOException() { + doThrow(new IOException()).when(pipedOutput).write(any()); + var fileContent = GrpcFileContentTestFactory.create(); + + assertThrows(TechnicalException.class, () -> { + observer.storeFileContent(fileContent); + }); + } + } + } + + @Nested + class TestHandleEndOfFile { + + @Mock + private File savedFileContent; + + private final IncomingFile incomingFile = IncomingFileTestFactory.createBuilder().file(null).build(); + + @BeforeEach + void setUp() { + doNothing().when(observer).closeOutputPipe(); + doReturn(savedFileContent).when(observer).getSavedFileContent(); + setCurrentFile(incomingFile); + } + + @Test + void shouldCallCloseOutputPipe() { + observer.handleEndOfFile(); + + verify(observer).closeOutputPipe(); + } + + @Nested + class TestOnGroupNameEmpty { + + @BeforeEach + void setUp() { + setGroupName(Optional.empty()); + } + + @Test + void shouldAddFileToRepresentations() { + var expectedIncomingFile = IncomingFileTestFactory.createBuilder().file(savedFileContent).build(); + + observer.handleEndOfFile(); + + assertThat(getRepresentations()).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedIncomingFile); + } + } + + @Nested + class TestOnGroupNameSet { + + @BeforeEach + void setUp() { + setGroupName(Optional.of(GrpcAttachmentFileTestFactory.GROUP_NAME)); + } + + @Test + void shouldAddFileToAttachments() { + var expectedIncomingFile = IncomingFileTestFactory.createBuilder().file(savedFileContent).build(); + + observer.handleEndOfFile(); + + var attachmentGroup = getAttachments().get(GrpcAttachmentFileTestFactory.GROUP_NAME); + assertThat(attachmentGroup).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedIncomingFile); + } + } + + @Test + void shouldCallResetFileReceiving() { + observer.handleEndOfFile(); + + verify(observer).resetFileReceiving(); + } + } + + @Nested + class TestGetSavedFileContent { + @BeforeEach + void setUp() { + doNothing().when(observer).closeInputPipe(); + } + + @Nested + class TestOnNoExceptions { + @Mock + private File fileContent; + + @BeforeEach + void setUp() { + setFileContent(CompletableFuture.completedFuture(fileContent)); + } + + @Test + void shouldReturnFile() { + var savedFileContent = observer.getSavedFileContent(); + + assertThat(savedFileContent).isSameAs(fileContent); + } + + @Test + void shouldCallCloseInputPipe() { + observer.getSavedFileContent(); + + verify(observer).closeInputPipe(); + } + } + + @Nested + class TestOnExecutionException { + + @BeforeEach + void setUp() { + setFileContent(CompletableFuture.failedFuture(new Exception())); + } + + @Test + void shouldThrowTechnicalException() { + assertThrows(TechnicalException.class, () -> observer.getSavedFileContent()); + } + + @Test + void shouldCallCloseInputPipe() { + try { + observer.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + verify(observer).closeInputPipe(); + } + } + + @Nested + class TestOnTimeoutException { + + @Mock + private CompletableFuture<File> fileFuture; + + @BeforeEach + @SneakyThrows + void setUp() { + setFileContent(fileFuture); + when(fileFuture.get(anyLong(), any())).thenThrow(new TimeoutException()); + } + + @Test + void shouldThrowTechnicalException() { + assertThrows(TechnicalException.class, () -> observer.getSavedFileContent()); + } + + @Test + void shouldCallCloseInputPipe() { + try { + observer.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + verify(observer).closeInputPipe(); + } + } + + @Nested + class TestOnInterruptedException { + + @Mock + private CompletableFuture<File> fileFuture; + + @BeforeEach + @SneakyThrows + void setUp() { + setFileContent(fileFuture); + when(fileFuture.get(anyLong(), any())).thenThrow(new InterruptedException()); + } + + @Test + void shouldThrowTechnicalException() { + assertThrows(TechnicalException.class, () -> observer.getSavedFileContent()); + } + + @Test + void shouldInterruptCurrentThread() { + try { + observer.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + assertThat(Thread.currentThread().isInterrupted()).isTrue(); + } + + @Test + void shouldCallCloseInputPipe() { + try { + observer.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + verify(observer).closeInputPipe(); + } + } + } + + @Nested + class TestResetFielReceiving { + + @BeforeEach + void setUp() { + setCurrentFile(IncomingFileTestFactory.create()); + setGroupName(Optional.of(GrpcAttachmentFileTestFactory.GROUP_NAME)); + setPipedOutput(mock(PipedOutputStream.class)); + setPipedOutput(mock(PipedOutputStream.class)); + setFileContent(CompletableFuture.completedFuture(mock(File.class))); + } + + @Test + void shouldResetCurrentFile() { + observer.resetFileReceiving(); + + assertThat(getCurrentFile()).isNull(); + } + + @Test + void shouldResetGroupName() { + observer.resetFileReceiving(); + + assertThat(getGroupName()).isEmpty(); + } + + @Test + void shouldResetPipedOutput() { + observer.resetFileReceiving(); + + assertThat(getPipedOutput()).isNull(); + } + + @Test + void shouldResetPipedInput() { + observer.resetFileReceiving(); + + assertThat(getPipedInput()).isNull(); + } + + @Test + void shouldResetReceivingFileContent() { + observer.resetFileReceiving(); + + assertThat(getFileContent()).isNull(); + } + } + + @Nested + class TestOnError { + + @BeforeEach + void mock() { + doNothing().when(observer).closeOutputPipe(); + doNothing().when(observer).closeInputPipe(); + } + + @Test + void shouldCallCloseOutputPipe() { + observer.onError(new Exception()); + + verify(observer).closeOutputPipe(); + } + + @Test + void shouldCallCloseInputPipe() { + observer.onError(new Exception()); + + verify(observer).closeInputPipe(); + } + } + + @Nested + class TestCloseOutputPipe { + + @Mock + private PipedOutputStream pipedOutput; + + @BeforeEach + void setUp() { + setPipedOutput(pipedOutput); + } + + @Test + @SneakyThrows + void shouldClosePipedOutput() { + observer.closeOutputPipe(); + + verify(pipedOutput).close(); + } + + @Test + @SneakyThrows + void shouldNotThrowException() { + doThrow(IOException.class).when(pipedOutput).close(); + + assertDoesNotThrow(() -> observer.closeOutputPipe()); + } + } + + @Nested + class TestCloseInputPipe { + + @Mock + private PipedInputStream pipedInput; + + @BeforeEach + void setUp() { + setPipedInput(pipedInput); + } + + @Test + @SneakyThrows + void shouldClosePipedInput() { + observer.closeInputPipe(); + + verify(pipedInput).close(); + } + + @Test + @SneakyThrows + void shouldNotThrowException() { + doThrow(IOException.class).when(pipedInput).close(); + + assertDoesNotThrow(() -> observer.closeInputPipe()); + } + } + + @Nested + class TestOnCompleted { + + private final FormData formData = FormDataTestFactory.create(); + + @BeforeEach + void mock() { + doReturn(formData).when(observer).assembleFormData(); + } + + @Test + void shouldCallAssembleFormData() { + observer.onCompleted(); + + verify(observer).assembleFormData(); + } + + @Test + void shouldCallFormDataConsumer() { + observer.onCompleted(); + + verify(formDataConsumer).accept(formData); + } + + @Test + void shouldCallResponseConsumer() { + observer.onCompleted(); + + verify(responseConsumer).accept(GrpcRouteForwardingResponse.getDefaultInstance()); + } + } + + @Nested + class TestAssembleFormData { + + @Nested + class TestOnFormDataNotSet { + + @Test + void shouldThrowIllegalStateException() { + assertThrows(IllegalStateException.class, () -> observer.assembleFormData()); + } + } + + @Nested + class TestOnFormDataSet { + + private final FormData formData = FormDataTestFactory.createBuilder() + .clearAttachments() + .clearRepresentations() + .numberOfAttachments(0) + .numberOfRepresentations(0) + .control(null) + .build(); + + private final List<IncomingFile> representations = FormDataTestFactory.REPRESENTATIONS; + private final Map.Entry<String, List<IncomingFile>> attachmentEntry = Map.entry( + IncomingFileGroupTestFactory.NAME, IncomingFileGroupTestFactory.INCOMING_FILES); + + @BeforeEach + void setUp() { + setFormData(formData); + setRepresentations(representations); + setAttachments(Map.ofEntries(attachmentEntry)); + } + + @Test + void shouldCallIncomingFileGroupMapper() { + observer.assembleFormData(); + + verify(incomingFileGroupMapper).fromMapEntry(attachmentEntry); + } + + @Test + void shouldReturnFormData() { + var expectedFormData = FormDataTestFactory.createBuilder() + .control(null) + .build(); + when(incomingFileGroupMapper.fromMapEntry(attachmentEntry)).thenReturn(IncomingFileGroupTestFactory.create()); + + var assembledFormData = observer.assembleFormData(); + + assertThat(assembledFormData).usingRecursiveComparison().isEqualTo(expectedFormData); + } + } + } + + private FormData getFormData() { + return (FormData) ReflectionTestUtils.getField(observer, "formData"); + } + + private void setFormData(FormData formData) { + ReflectionTestUtils.setField(observer, "formData", formData); + } + + @SuppressWarnings("unchecked") + private Optional<String> getGroupName() { + return (Optional<String>) ReflectionTestUtils.getField(observer, "groupName"); + } + + private void setGroupName(Optional<String> groupName) { + ReflectionTestUtils.setField(observer, "groupName", groupName); + } + + private IncomingFile getCurrentFile() { + return (IncomingFile) ReflectionTestUtils.getField(observer, "currentFile"); + } + + private void setCurrentFile(IncomingFile incomingFile) { + ReflectionTestUtils.setField(observer, "currentFile", incomingFile); + } + + private void setFileContent(CompletableFuture<File> fileFuture) { + ReflectionTestUtils.setField(observer, "receivingFileContent", fileFuture); + } + + @SuppressWarnings("unchecked") + private CompletableFuture<File> getFileContent() { + return (CompletableFuture<File>) ReflectionTestUtils.getField(observer, "receivingFileContent"); + } + + private PipedInputStream getPipedInput() { + return (PipedInputStream) ReflectionTestUtils.getField(observer, "pipedInput"); + } + + private void setPipedInput(PipedInputStream pipedInput) { + ReflectionTestUtils.setField(observer, "pipedInput", pipedInput); + } + + private PipedOutputStream getPipedOutput() { + return (PipedOutputStream) ReflectionTestUtils.getField(observer, "pipedOutput"); + } + + private void setPipedOutput(PipedOutputStream pipedOutput) { + ReflectionTestUtils.setField(observer, "pipedOutput", pipedOutput); + } + + @SuppressWarnings("unchecked") + private List<IncomingFile> getRepresentations() { + return (List<IncomingFile>) ReflectionTestUtils.getField(observer, "representations"); + } + + private void setRepresentations(List<IncomingFile> representations) { + ReflectionTestUtils.setField(observer, "representations", representations); + } + + @SuppressWarnings("unchecked") + private Map<String, List<IncomingFile>> getAttachments() { + return (Map<String, List<IncomingFile>>) ReflectionTestUtils.getField(observer, "attachments"); + } + + private void setAttachments(Map<String, List<IncomingFile>> attachments) { + ReflectionTestUtils.setField(observer, "attachments", attachments); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java index 12382dcfe..ec48f44e4 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java @@ -23,15 +23,14 @@ */ package de.ozgcloud.eingang.forwarder; -import com.thedeanda.lorem.LoremIpsum; - +import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile; import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile.Builder; public class GrpcAttachmentFileTestFactory { - public static final String GROUP_NAME = LoremIpsum.getInstance().getWords(1); + public static final String GROUP_NAME = IncomingFileGroupTestFactory.NAME; public static GrpcAttachmentFile create() { return createBuilder().build(); diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentTestFactory.java new file mode 100644 index 000000000..e5593e13f --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentTestFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import de.ozgcloud.eingang.forwarding.GrpcAttachment; +import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile; +import de.ozgcloud.eingang.forwarding.GrpcFileContent; + +public class GrpcAttachmentTestFactory { + + public static final GrpcAttachmentFile FILE = GrpcAttachmentFileTestFactory.create(); + public static final GrpcFileContent CONTENT = GrpcFileContentTestFactory.create(); + + public static GrpcAttachment createWithFile() { + return GrpcAttachment.newBuilder() + .setFile(FILE) + .build(); + } + + public static GrpcAttachment createWithContent() { + return GrpcAttachment.newBuilder() + .setContent(CONTENT) + .build(); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcFileContentTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcFileContentTestFactory.java new file mode 100644 index 000000000..d4040f975 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcFileContentTestFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import com.google.protobuf.ByteString; +import com.thedeanda.lorem.LoremIpsum; + +import de.ozgcloud.eingang.forwarding.GrpcFileContent; +import de.ozgcloud.eingang.forwarding.GrpcFileContent.Builder; + +public class GrpcFileContentTestFactory { + + public static final boolean IS_END_OF_FILE = false; + public static final byte[] CONTENT = LoremIpsum.getInstance().getWords(10).getBytes(); + + public static GrpcFileContent create() { + return createBuilder().build(); + } + + public static Builder createBuilder() { + return GrpcFileContent.newBuilder() + .setContent(ByteString.copyFrom(CONTENT)) + .setIsEndOfFile(IS_END_OF_FILE); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationTestFactory.java new file mode 100644 index 000000000..e437c900d --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationTestFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import de.ozgcloud.eingang.forwarding.GrpcFileContent; +import de.ozgcloud.eingang.forwarding.GrpcRepresentation; +import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile; + +public class GrpcRepresentationTestFactory { + + public static final GrpcRepresentationFile FILE = GrpcRepresentationFileTestFactory.create(); + public static final GrpcFileContent CONTENT = GrpcFileContentTestFactory.create(); + + public static GrpcRepresentation createWithFile() { + return GrpcRepresentation.newBuilder() + .setFile(FILE) + .build(); + } + + public static GrpcRepresentation createWithContent() { + return GrpcRepresentation.newBuilder() + .setContent(CONTENT) + .build(); + } +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java new file mode 100644 index 000000000..a05ac9a84 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import de.ozgcloud.eingang.forwarding.GrpcAttachment; +import de.ozgcloud.eingang.forwarding.GrpcRepresentation; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; + +public class GrpcRouteForwardingRequestTestFactory { + + public static final GrpcRepresentation REPRESENTATION = GrpcRepresentationTestFactory.createWithFile(); + public static final GrpcAttachment ATTACHMENT = GrpcAttachmentTestFactory.createWithFile(); + public static final GrpcRouteForwarding ROUTE_FORWARDING = GrpcRouteForwardingTestFactory.create(); + + public static GrpcRouteForwardingRequest createWithRouteForwarding() { + return GrpcRouteForwardingRequest.newBuilder() + .setRouteForwarding(ROUTE_FORWARDING) + .build(); + } + + public static GrpcRouteForwardingRequest createWithAttachment() { + return GrpcRouteForwardingRequest.newBuilder() + .setAttachment(ATTACHMENT) + .build(); + } + + public static GrpcRouteForwardingRequest createWithRepresentation() { + return GrpcRouteForwardingRequest.newBuilder() + .setRepresentation(REPRESENTATION) + .build(); + } +} -- GitLab From f7cfe07f8654d999377eed3392d97b1f72575914 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Tue, 18 Mar 2025 12:03:57 +0100 Subject: [PATCH 19/28] OZG-7573 add license header --- .../eingang/fim/AntragstellerMapper.java | 23 +++++++++++++++++++ .../de/ozgcloud/eingang/fim/FimDataUtil.java | 23 +++++++++++++++++++ .../eingang/fim/FimDocumentReader.java | 23 +++++++++++++++++++ .../ozgcloud/eingang/fim/FimSchemeHelper.java | 23 +++++++++++++++++++ .../de/ozgcloud/eingang/fim/HeaderMapper.java | 23 +++++++++++++++++++ .../common/errorhandling/FimException.java | 23 +++++++++++++++++++ .../fim/common/xml/DocumentHelper.java | 23 +++++++++++++++++++ .../eingang/fim/AntragstellerMapperTest.java | 23 +++++++++++++++++++ .../eingang/fim/AntragstellerTestFactory.java | 23 +++++++++++++++++++ .../eingang/fim/FimBasedAdapterITCase.java | 23 +++++++++++++++++++ .../ozgcloud/eingang/fim/FimDataUtilTest.java | 23 +++++++++++++++++++ .../eingang/fim/FimDocumentTestHelper.java | 23 +++++++++++++++++++ .../eingang/fim/FimSchemeHelperTest.java | 23 +++++++++++++++++++ .../ozgcloud/eingang/fim/FimServiceTest.java | 23 +++++++++++++++++++ .../eingang/fim/HeaderMapperTest.java | 23 +++++++++++++++++++ .../eingang/forwarder/FileServiceTest.java | 23 +++++++++++++++++++ .../ozgcloud/eingang/common/zufi/XzufiId.java | 23 +++++++++++++++++++ .../semantik/common/FormDataTestFactory.java | 23 +++++++++++++++++++ 18 files changed, 414 insertions(+) diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerMapper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerMapper.java index 0c65466d7..e7b648eee 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerMapper.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerMapper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.util.Map; diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java index 6d5273567..b3dea53e5 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.util.List; diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDocumentReader.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDocumentReader.java index de7e3961c..8301f01ea 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDocumentReader.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDocumentReader.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.util.Collections; diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeHelper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeHelper.java index 054589340..9fefeba4d 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeHelper.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeHelper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.util.List; diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/HeaderMapper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/HeaderMapper.java index 63befb663..632636410 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/HeaderMapper.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/HeaderMapper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.util.List; diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/errorhandling/FimException.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/errorhandling/FimException.java index 68be9eb44..c7333daf4 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/errorhandling/FimException.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/errorhandling/FimException.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim.common.errorhandling; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/xml/DocumentHelper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/xml/DocumentHelper.java index 2368cd4dd..966b2cc08 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/xml/DocumentHelper.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/common/xml/DocumentHelper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim.common.xml; import java.io.File; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerMapperTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerMapperTest.java index f6daa78ea..8dd4950ec 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerMapperTest.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerMapperTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import static org.assertj.core.api.Assertions.*; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerTestFactory.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerTestFactory.java index e72806960..6e14ba107 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerTestFactory.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/AntragstellerTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.util.HashMap; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterITCase.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterITCase.java index e32906bc4..ac669d63c 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterITCase.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterITCase.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import static org.assertj.core.api.Assertions.*; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataUtilTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataUtilTest.java index cb48785bc..631029fe3 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataUtilTest.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataUtilTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import static org.assertj.core.api.Assertions.*; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDocumentTestHelper.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDocumentTestHelper.java index 610263cc8..e5bbe51da 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDocumentTestHelper.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDocumentTestHelper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import java.io.File; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimSchemeHelperTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimSchemeHelperTest.java index 7553fefb3..d76848444 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimSchemeHelperTest.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimSchemeHelperTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import static org.assertj.core.api.Assertions.*; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceTest.java index 4d090842c..c9ff9d8de 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceTest.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import static org.assertj.core.api.Assertions.*; diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/HeaderMapperTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/HeaderMapperTest.java index eef87830a..b55225451 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/HeaderMapperTest.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/HeaderMapperTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.fim; import static org.assertj.core.api.Assertions.*; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java index 795bcf585..dbf23b168 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; import static org.assertj.core.api.Assertions.*; diff --git a/router/src/main/java/de/ozgcloud/eingang/common/zufi/XzufiId.java b/router/src/main/java/de/ozgcloud/eingang/common/zufi/XzufiId.java index ff731658b..bbcb44b94 100644 --- a/router/src/main/java/de/ozgcloud/eingang/common/zufi/XzufiId.java +++ b/router/src/main/java/de/ozgcloud/eingang/common/zufi/XzufiId.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.common.zufi; import lombok.Builder; diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java index 83b265781..594048a72 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/FormDataTestFactory.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2025 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.eingang.semantik.common; import java.util.HashMap; -- GitLab From 5093746ca522554be9d99e8042f5ecf53f620a14 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Thu, 20 Mar 2025 08:54:07 +0100 Subject: [PATCH 20/28] OZG-7573 only read content if EOF is false --- .../EingangStubReceiverStreamObserver.java | 13 ++-- ...EingangStubReceiverStreamObserverTest.java | 69 ++++++++++++------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index d5f1aa22a..1d355f5fd 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -156,13 +156,14 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou if (Objects.isNull(currentFile)) { throw new IllegalStateException("File content received before metadata."); } - try { - pipedOutput.write(content.getContent().toByteArray()); - if (content.getIsEndOfFile()) { - handleEndOfFile(); + if (content.getIsEndOfFile()) { + handleEndOfFile(); + } else { + try { + pipedOutput.write(content.getContent().toByteArray()); + } catch (IOException e) { + throw new TechnicalException("Error when writing file content.", e); } - } catch (IOException e) { - throw new TechnicalException("Error when writing file content.", e); } } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java index f4bacd0b2..d14d99362 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -502,42 +502,61 @@ class EingangStubReceiverStreamObserverTest { setCurrentFile(incomingFile); } - @Test - @SneakyThrows - void shouldWriteContentToOutputStream() { - observer.storeFileContent(GrpcFileContentTestFactory.create()); + @Nested + class TestOnEndOfFile { - verify(pipedOutput).write(GrpcFileContentTestFactory.CONTENT); - } + private GrpcFileContent fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(true).build(); - @Test - void shouldCallHandleEndOfFile() { - doNothing().when(observer).handleEndOfFile(); - var fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(true).build(); + @BeforeEach + void setUp() { + doNothing().when(observer).handleEndOfFile(); + } + + @Test + void shouldCallHandleEndOfFile() { + observer.storeFileContent(fileContent); + + verify(observer).handleEndOfFile(); + } - observer.storeFileContent(fileContent); + @Test + @SneakyThrows + void shouldNotWriteContentToOutputStream() { + observer.storeFileContent(fileContent); - verify(observer).handleEndOfFile(); + verify(pipedOutput, never()).write(any()); + } } - @Test - void shouldNotCallHandleEndOfFile() { - var fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(false).build(); + @Nested + class TestOnNotEndOfFile { - observer.storeFileContent(fileContent); + private GrpcFileContent fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(false).build(); - verify(observer, never()).handleEndOfFile(); - } + @Test + @SneakyThrows + void shouldWriteContentToOutputStream() { + observer.storeFileContent(fileContent); - @Test - @SneakyThrows - void shouldThrowTechnicalExceptionOnIOException() { - doThrow(new IOException()).when(pipedOutput).write(any()); - var fileContent = GrpcFileContentTestFactory.create(); + verify(pipedOutput).write(GrpcFileContentTestFactory.CONTENT); + } - assertThrows(TechnicalException.class, () -> { + @Test + void shouldNotCallHandleEndOfFile() { observer.storeFileContent(fileContent); - }); + + verify(observer, never()).handleEndOfFile(); + } + + @Test + @SneakyThrows + void shouldThrowTechnicalExceptionOnIOException() { + doThrow(new IOException()).when(pipedOutput).write(any()); + + assertThrows(TechnicalException.class, () -> { + observer.storeFileContent(fileContent); + }); + } } } } -- GitLab From 0cf5dd0e163633de7196bf368d21d3429089530e Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Thu, 20 Mar 2025 10:57:37 +0100 Subject: [PATCH 21/28] OZG-7573 add error handler --- .../EingangStubReceiverStreamObserver.java | 5 ++- .../forwarder/RouteForwardingGrpcService.java | 5 +++ ...EingangStubReceiverStreamObserverTest.java | 12 ++++++ .../RouteForwardingGrpcServiceTest.java | 41 ++++++++++++++++--- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 1d355f5fd..0d174825d 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -67,17 +67,19 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou private final Function<InputStream, CompletableFuture<File>> fileSaver; private final Consumer<FormData> formDataConsumer; private final Consumer<GrpcRouteForwardingResponse> responseConsumer; + private final Consumer<Throwable> onErrorHandler; @Builder public EingangStubReceiverStreamObserver(RouteForwardingMapper routeForwardingMapper, IncomingFileMapper incomingFileMapper, IncomingFileGroupMapper incomingFileGroupMapper, Function<InputStream, CompletableFuture<File>> fileSaver, - Consumer<FormData> formDataConsumer, Consumer<GrpcRouteForwardingResponse> responseConsumer) { + Consumer<FormData> formDataConsumer, Consumer<GrpcRouteForwardingResponse> responseConsumer, Consumer<Throwable> onErrorHandler) { this.routeForwardingMapper = routeForwardingMapper; this.incomingFileMapper = incomingFileMapper; this.incomingFileGroupMapper = incomingFileGroupMapper; this.fileSaver = fileSaver; this.formDataConsumer = formDataConsumer; this.responseConsumer = responseConsumer; + this.onErrorHandler = onErrorHandler; } private FormData formData; @@ -202,6 +204,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou LOG.error("Error happened. Receiving stream closed.", t); closeOutputPipe(); closeInputPipe(); + onErrorHandler.accept(t); } void closeOutputPipe() { diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java index 322e7361f..d08d98e8e 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java @@ -52,6 +52,7 @@ public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.Route .incomingFileGroupMapper(incomingFileGroupMapper) .formDataConsumer(routeForwardingService::route) .responseConsumer(repsonse -> respondWith(responseObserver, repsonse)) + .onErrorHandler(error -> handleError(error, responseObserver)) .build(); } @@ -64,4 +65,8 @@ public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.Route responseObserver.onCompleted(); } + public void handleError(Throwable error, StreamObserver<GrpcRouteForwardingResponse> responseObserver) { + responseObserver.onError(error); + } + } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java index d14d99362..fc502fe69 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -76,6 +76,8 @@ class EingangStubReceiverStreamObserverTest { private Consumer<FormData> formDataConsumer; @Mock private Consumer<GrpcRouteForwardingResponse> responseConsumer; + @Mock + private Consumer<Throwable> onErrorHandler; @BeforeEach void setUp() { @@ -86,6 +88,7 @@ class EingangStubReceiverStreamObserverTest { .incomingFileGroupMapper(incomingFileGroupMapper) .formDataConsumer(formDataConsumer) .responseConsumer(responseConsumer) + .onErrorHandler(onErrorHandler) .build()); } @@ -827,6 +830,15 @@ class EingangStubReceiverStreamObserverTest { verify(observer).closeInputPipe(); } + + @Test + void shouldCallOnErrorHandler() { + var exception = new Exception(); + + observer.onError(exception); + + verify(onErrorHandler).accept(exception); + } } @Nested diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java index 35ac8140c..5c94fb60b 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java @@ -122,6 +122,16 @@ class RouteForwardingGrpcServiceTest { verify(service).respondWith(responseObserver, GrpcRouteForwardingResponse.getDefaultInstance()); } + @Test + void shouldSetOnErrorHandler() { + var error = new Throwable(); + + var observer = service.routeForwarding(responseObserver); + + callOnErrorHandler(observer, error); + verify(service).handleError(error, responseObserver); + } + @SuppressWarnings("unchecked") private void callFileSaver(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { var fileSaver = (Function<InputStream, CompletableFuture<File>>) ReflectionTestUtils.getField(uploadObserver, "fileSaver"); @@ -129,18 +139,15 @@ class RouteForwardingGrpcServiceTest { } private RouteForwardingMapper getRouteForwardingMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { - var routeForwardingMapper = (RouteForwardingMapper) ReflectionTestUtils.getField(uploadObserver, "routeForwardingMapper"); - return routeForwardingMapper; + return (RouteForwardingMapper) ReflectionTestUtils.getField(uploadObserver, "routeForwardingMapper"); } private IncomingFileMapper getIncomingFileMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { - var incomingFileMapper = (IncomingFileMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileMapper"); - return incomingFileMapper; + return (IncomingFileMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileMapper"); } private IncomingFileGroupMapper getIncomingFileGroupMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { - var incomingFileGroupMapper = (IncomingFileGroupMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileGroupMapper"); - return incomingFileGroupMapper; + return (IncomingFileGroupMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileGroupMapper"); } @SuppressWarnings("unchecked") @@ -154,6 +161,12 @@ class RouteForwardingGrpcServiceTest { var responseConsumer = (Consumer<GrpcRouteForwardingResponse>) ReflectionTestUtils.getField(uploadObserver, "responseConsumer"); responseConsumer.accept(response); } + + @SuppressWarnings("unchecked") + private void callOnErrorHandler(StreamObserver<GrpcRouteForwardingRequest> uploadObserver, Throwable throwable) { + var onErrorHandler = (Consumer<Throwable>) ReflectionTestUtils.getField(uploadObserver, "onErrorHandler"); + onErrorHandler.accept(throwable); + } } @Nested @@ -205,4 +218,20 @@ class RouteForwardingGrpcServiceTest { inOrder.verify(responseObserver).onCompleted(); } } + + @Nested + class TestHandleError { + + @Mock + private StreamObserver<GrpcRouteForwardingResponse> responseObserver; + + @Test + void shouldDoNothing() { + var error = new Throwable(); + + service.handleError(error, responseObserver); + + verify(responseObserver).onError(error); + } + } } -- GitLab From f5887f78db667568df79678e4420c72d2be88de6 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Thu, 20 Mar 2025 11:59:45 +0100 Subject: [PATCH 22/28] Revert "OZG-7573 add error handler" This reverts commit 0cf5dd0e163633de7196bf368d21d3429089530e. --- .../EingangStubReceiverStreamObserver.java | 5 +-- .../forwarder/RouteForwardingGrpcService.java | 5 --- ...EingangStubReceiverStreamObserverTest.java | 12 ------ .../RouteForwardingGrpcServiceTest.java | 41 +++---------------- 4 files changed, 7 insertions(+), 56 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 0d174825d..1d355f5fd 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -67,19 +67,17 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou private final Function<InputStream, CompletableFuture<File>> fileSaver; private final Consumer<FormData> formDataConsumer; private final Consumer<GrpcRouteForwardingResponse> responseConsumer; - private final Consumer<Throwable> onErrorHandler; @Builder public EingangStubReceiverStreamObserver(RouteForwardingMapper routeForwardingMapper, IncomingFileMapper incomingFileMapper, IncomingFileGroupMapper incomingFileGroupMapper, Function<InputStream, CompletableFuture<File>> fileSaver, - Consumer<FormData> formDataConsumer, Consumer<GrpcRouteForwardingResponse> responseConsumer, Consumer<Throwable> onErrorHandler) { + Consumer<FormData> formDataConsumer, Consumer<GrpcRouteForwardingResponse> responseConsumer) { this.routeForwardingMapper = routeForwardingMapper; this.incomingFileMapper = incomingFileMapper; this.incomingFileGroupMapper = incomingFileGroupMapper; this.fileSaver = fileSaver; this.formDataConsumer = formDataConsumer; this.responseConsumer = responseConsumer; - this.onErrorHandler = onErrorHandler; } private FormData formData; @@ -204,7 +202,6 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou LOG.error("Error happened. Receiving stream closed.", t); closeOutputPipe(); closeInputPipe(); - onErrorHandler.accept(t); } void closeOutputPipe() { diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java index d08d98e8e..322e7361f 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java @@ -52,7 +52,6 @@ public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.Route .incomingFileGroupMapper(incomingFileGroupMapper) .formDataConsumer(routeForwardingService::route) .responseConsumer(repsonse -> respondWith(responseObserver, repsonse)) - .onErrorHandler(error -> handleError(error, responseObserver)) .build(); } @@ -65,8 +64,4 @@ public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.Route responseObserver.onCompleted(); } - public void handleError(Throwable error, StreamObserver<GrpcRouteForwardingResponse> responseObserver) { - responseObserver.onError(error); - } - } diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java index fc502fe69..d14d99362 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -76,8 +76,6 @@ class EingangStubReceiverStreamObserverTest { private Consumer<FormData> formDataConsumer; @Mock private Consumer<GrpcRouteForwardingResponse> responseConsumer; - @Mock - private Consumer<Throwable> onErrorHandler; @BeforeEach void setUp() { @@ -88,7 +86,6 @@ class EingangStubReceiverStreamObserverTest { .incomingFileGroupMapper(incomingFileGroupMapper) .formDataConsumer(formDataConsumer) .responseConsumer(responseConsumer) - .onErrorHandler(onErrorHandler) .build()); } @@ -830,15 +827,6 @@ class EingangStubReceiverStreamObserverTest { verify(observer).closeInputPipe(); } - - @Test - void shouldCallOnErrorHandler() { - var exception = new Exception(); - - observer.onError(exception); - - verify(onErrorHandler).accept(exception); - } } @Nested diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java index 5c94fb60b..35ac8140c 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java @@ -122,16 +122,6 @@ class RouteForwardingGrpcServiceTest { verify(service).respondWith(responseObserver, GrpcRouteForwardingResponse.getDefaultInstance()); } - @Test - void shouldSetOnErrorHandler() { - var error = new Throwable(); - - var observer = service.routeForwarding(responseObserver); - - callOnErrorHandler(observer, error); - verify(service).handleError(error, responseObserver); - } - @SuppressWarnings("unchecked") private void callFileSaver(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { var fileSaver = (Function<InputStream, CompletableFuture<File>>) ReflectionTestUtils.getField(uploadObserver, "fileSaver"); @@ -139,15 +129,18 @@ class RouteForwardingGrpcServiceTest { } private RouteForwardingMapper getRouteForwardingMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { - return (RouteForwardingMapper) ReflectionTestUtils.getField(uploadObserver, "routeForwardingMapper"); + var routeForwardingMapper = (RouteForwardingMapper) ReflectionTestUtils.getField(uploadObserver, "routeForwardingMapper"); + return routeForwardingMapper; } private IncomingFileMapper getIncomingFileMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { - return (IncomingFileMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileMapper"); + var incomingFileMapper = (IncomingFileMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileMapper"); + return incomingFileMapper; } private IncomingFileGroupMapper getIncomingFileGroupMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { - return (IncomingFileGroupMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileGroupMapper"); + var incomingFileGroupMapper = (IncomingFileGroupMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileGroupMapper"); + return incomingFileGroupMapper; } @SuppressWarnings("unchecked") @@ -161,12 +154,6 @@ class RouteForwardingGrpcServiceTest { var responseConsumer = (Consumer<GrpcRouteForwardingResponse>) ReflectionTestUtils.getField(uploadObserver, "responseConsumer"); responseConsumer.accept(response); } - - @SuppressWarnings("unchecked") - private void callOnErrorHandler(StreamObserver<GrpcRouteForwardingRequest> uploadObserver, Throwable throwable) { - var onErrorHandler = (Consumer<Throwable>) ReflectionTestUtils.getField(uploadObserver, "onErrorHandler"); - onErrorHandler.accept(throwable); - } } @Nested @@ -218,20 +205,4 @@ class RouteForwardingGrpcServiceTest { inOrder.verify(responseObserver).onCompleted(); } } - - @Nested - class TestHandleError { - - @Mock - private StreamObserver<GrpcRouteForwardingResponse> responseObserver; - - @Test - void shouldDoNothing() { - var error = new Throwable(); - - service.handleError(error, responseObserver); - - verify(responseObserver).onError(error); - } - } } -- GitLab From 6fd814680f5b1f49ad9a451918b9f0819266b20c Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Thu, 20 Mar 2025 14:23:27 +0100 Subject: [PATCH 23/28] Ozg-7573 apply code review --- .../EingangStubReceiverStreamObserver.java | 17 +++++++------- ...EingangStubReceiverStreamObserverTest.java | 22 +++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 1d355f5fd..fd810664e 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -57,7 +57,7 @@ import lombok.Builder; import lombok.extern.log4j.Log4j2; @Log4j2 -public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwardingRequest> { +class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwardingRequest> { private static final int CHUNK_SIZE = 1024 * 64; private static final long TIMEOUT_MINUTES = 10; @@ -81,11 +81,11 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou } private FormData formData; - private List<IncomingFile> representations = new ArrayList<>(); - private Map<String, List<IncomingFile>> attachments = new HashMap<>(); + private final List<IncomingFile> representations = new ArrayList<>(); + private final Map<String, List<IncomingFile>> attachments = new HashMap<>(); private IncomingFile currentFile; - private Optional<String> groupName = Optional.empty(); + private String groupName; private PipedOutputStream pipedOutput; private PipedInputStream pipedInput; private CompletableFuture<File> receivingFileContent; @@ -113,7 +113,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou void handleAttachment(GrpcAttachment attachment) { if (attachment.hasFile()) { setCurrentMetadata(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); - groupName = Optional.of(attachment.getFile().getGroupName()); + groupName = attachment.getFile().getGroupName(); } else { handleFileContent(attachment.getContent()); } @@ -130,7 +130,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou void setCurrentMetadata(IncomingFile metaData) { if (Objects.nonNull(currentFile)) { - throw new IllegalStateException("Received additional file before previos file reached the end."); + throw new IllegalStateException("Received additional file before previous file reached the end."); } currentFile = metaData; } @@ -170,7 +170,8 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou void handleEndOfFile() { closeOutputPipe(); var completedIncomingFile = currentFile.toBuilder().file(getSavedFileContent()).build(); - groupName.map(group -> attachments.computeIfAbsent(group, s -> new ArrayList<IncomingFile>())) + Optional.ofNullable(groupName) + .map(group -> attachments.computeIfAbsent(group, s -> new ArrayList<>())) .orElse(representations) .add(completedIncomingFile); resetFileReceiving(); @@ -191,7 +192,7 @@ public class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRou void resetFileReceiving() { currentFile = null; - groupName = Optional.empty(); + groupName = null; pipedOutput = null; pipedInput = null; receivingFileContent = null; diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java index d14d99362..04d21376b 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -35,7 +35,6 @@ import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; @@ -235,7 +234,7 @@ class EingangStubReceiverStreamObserverTest { void shouldSetGroupName() { observer.handleAttachment(attachmentWithFile); - assertThat(getGroupName()).contains(GrpcAttachmentFileTestFactory.GROUP_NAME); + assertThat(getGroupName()).isEqualTo(GrpcAttachmentFileTestFactory.GROUP_NAME); } @Test @@ -274,7 +273,7 @@ class EingangStubReceiverStreamObserverTest { void shouldNotSetGroupName() { observer.handleAttachment(attachmentWithContent); - assertThat(getGroupName()).isEmpty(); + assertThat(getGroupName()).isNull(); } } } @@ -584,11 +583,11 @@ class EingangStubReceiverStreamObserverTest { } @Nested - class TestOnGroupNameEmpty { + class TestOnGroupNameNull { @BeforeEach void setUp() { - setGroupName(Optional.empty()); + setGroupName(null); } @Test @@ -606,7 +605,7 @@ class EingangStubReceiverStreamObserverTest { @BeforeEach void setUp() { - setGroupName(Optional.of(GrpcAttachmentFileTestFactory.GROUP_NAME)); + setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); } @Test @@ -763,7 +762,7 @@ class EingangStubReceiverStreamObserverTest { @BeforeEach void setUp() { setCurrentFile(IncomingFileTestFactory.create()); - setGroupName(Optional.of(GrpcAttachmentFileTestFactory.GROUP_NAME)); + setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); setPipedOutput(mock(PipedOutputStream.class)); setPipedOutput(mock(PipedOutputStream.class)); setFileContent(CompletableFuture.completedFuture(mock(File.class))); @@ -780,7 +779,7 @@ class EingangStubReceiverStreamObserverTest { void shouldResetGroupName() { observer.resetFileReceiving(); - assertThat(getGroupName()).isEmpty(); + assertThat(getGroupName()).isNull(); } @Test @@ -980,12 +979,11 @@ class EingangStubReceiverStreamObserverTest { ReflectionTestUtils.setField(observer, "formData", formData); } - @SuppressWarnings("unchecked") - private Optional<String> getGroupName() { - return (Optional<String>) ReflectionTestUtils.getField(observer, "groupName"); + private String getGroupName() { + return (String) ReflectionTestUtils.getField(observer, "groupName"); } - private void setGroupName(Optional<String> groupName) { + private void setGroupName(String groupName) { ReflectionTestUtils.setField(observer, "groupName", groupName); } -- GitLab From 9b808646c3a89ceedb6fe3df822719d99f2bb14c Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Thu, 20 Mar 2025 14:35:41 +0100 Subject: [PATCH 24/28] OZG-7573 refactor handleEndOfFile --- .../EingangStubReceiverStreamObserver.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index fd810664e..ec9080a75 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -33,7 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -170,13 +169,22 @@ class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwa void handleEndOfFile() { closeOutputPipe(); var completedIncomingFile = currentFile.toBuilder().file(getSavedFileContent()).build(); - Optional.ofNullable(groupName) - .map(group -> attachments.computeIfAbsent(group, s -> new ArrayList<>())) - .orElse(representations) - .add(completedIncomingFile); + if (Objects.isNull(groupName)) { + addAsRepresentation(completedIncomingFile); + } else { + addAsAttachment(completedIncomingFile); + } resetFileReceiving(); } + private void addAsRepresentation(IncomingFile completedIncomingFile) { + representations.add(completedIncomingFile); + } + + private void addAsAttachment(IncomingFile completedIncomingFile) { + attachments.computeIfAbsent(groupName, s -> new ArrayList<>()).add(completedIncomingFile); + } + File getSavedFileContent() { try { return receivingFileContent.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); -- GitLab From 7dc12961d47a0816ce9eca12437aafbb85b4a0ab Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Fri, 21 Mar 2025 08:26:38 +0100 Subject: [PATCH 25/28] OZG-7573 refactor EingangStubReceiverStreamObserver and create ContentCollector --- .../formdata/IncomingFileTestFactory.java | 4 +- .../eingang/forwarder/ContentCollector.java | 112 +++ .../EingangStubReceiverStreamObserver.java | 125 +--- .../forwarder/ContentCollectorTest.java | 484 +++++++++++++ ...EingangStubReceiverStreamObserverTest.java | 657 +++--------------- 5 files changed, 735 insertions(+), 647 deletions(-) create mode 100644 forwarder/src/main/java/de/ozgcloud/eingang/forwarder/ContentCollector.java create mode 100644 forwarder/src/test/java/de/ozgcloud/eingang/forwarder/ContentCollectorTest.java diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java index f377a61cd..85a108436 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java @@ -23,6 +23,7 @@ */ package de.ozgcloud.eingang.common.formdata; +import java.io.File; import java.util.UUID; import org.springframework.http.MediaType; @@ -41,6 +42,7 @@ public class IncomingFileTestFactory { public static final String PDF_CONTENT_TYPE = MediaType.APPLICATION_PDF_VALUE; public static final String JSON_CONTENT_TYPE = MediaType.APPLICATION_JSON_VALUE; public static final byte[] CONTENT = "TESTCONTENT1".getBytes(); + public static final File FILE = TempFileUtils.writeTmpFile(CONTENT); public static final long SIZE = 12; public static IncomingFile create() { @@ -53,7 +55,7 @@ public class IncomingFileTestFactory { .vendorId(VENDOR_ID) .name(NAME) .contentType(CONTENT_TYPE) - .file(TempFileUtils.writeTmpFile(CONTENT)) + .file(FILE) .size(SIZE); } diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/ContentCollector.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/ContentCollector.java new file mode 100644 index 000000000..5099f2385 --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/ContentCollector.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Function; + +import org.apache.commons.io.IOUtils; + +import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.forwarding.GrpcFileContent; +import lombok.Builder; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +class ContentCollector { + private static final int CHUNK_SIZE = 1024 * 64; + private static final long TIMEOUT_MINUTES = 10; + + private final IncomingFile incomingFile; + + private final PipedOutputStream pipedOutput; + private final PipedInputStream pipedInput; + private final CompletableFuture<File> receivingFileContent; + + @Builder + private ContentCollector(Function<InputStream, CompletableFuture<File>> fileSaver, IncomingFile incomingFile) { + this.incomingFile = incomingFile; + try { + pipedInput = new PipedInputStream(CHUNK_SIZE); + pipedOutput = new PipedOutputStream(pipedInput); + receivingFileContent = fileSaver.apply(pipedInput); + } catch (IOException e) { + throw new TechnicalException("Upload initialization failed", e); + } + } + + public Optional<IncomingFile> collect(GrpcFileContent fileContent) { + if (fileContent.getIsEndOfFile()) { + return Optional.of(handleEndOfFile()); + } + try { + pipedOutput.write(fileContent.getContent().toByteArray()); + } catch (IOException e) { + throw new TechnicalException("Error when writing file content.", e); + } + return Optional.empty(); + } + + IncomingFile handleEndOfFile() { + closeOutputPipe(); + return incomingFile.toBuilder().file(getSavedFileContent()).build(); + } + + File getSavedFileContent() { + try { + return receivingFileContent.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); + } catch (ExecutionException | TimeoutException e) { + throw new TechnicalException("Receiving file failed.", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TechnicalException("Upload was interrupted.", e); + } finally { + closeInputPipe(); + } + } + + public void close() { + closeOutputPipe(); + closeInputPipe(); + } + + void closeOutputPipe() { + IOUtils.closeQuietly(pipedOutput, e -> LOG.error("Cannot close output stream.", e)); + } + + void closeInputPipe() { + IOUtils.closeQuietly(pipedInput, e -> LOG.error("Cannot close input stream.", e)); + } + +} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index ec9080a75..45f253538 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -24,29 +24,19 @@ package de.ozgcloud.eingang.forwarder; import java.io.File; -import java.io.IOException; import java.io.InputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Function; -import org.apache.commons.io.IOUtils; - -import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.forwarding.GrpcAttachment; -import de.ozgcloud.eingang.forwarding.GrpcFileContent; import de.ozgcloud.eingang.forwarding.GrpcRepresentation; import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest; @@ -58,8 +48,6 @@ import lombok.extern.log4j.Log4j2; @Log4j2 class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwardingRequest> { - private static final int CHUNK_SIZE = 1024 * 64; - private static final long TIMEOUT_MINUTES = 10; private final RouteForwardingMapper routeForwardingMapper; private final IncomingFileMapper incomingFileMapper; private final IncomingFileGroupMapper incomingFileGroupMapper; @@ -83,11 +71,9 @@ class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwa private final List<IncomingFile> representations = new ArrayList<>(); private final Map<String, List<IncomingFile>> attachments = new HashMap<>(); - private IncomingFile currentFile; private String groupName; - private PipedOutputStream pipedOutput; - private PipedInputStream pipedInput; - private CompletableFuture<File> receivingFileContent; + private ContentCollector attachmentCollector; + private ContentCollector representationCollector; @Override public synchronized void onNext(GrpcRouteForwardingRequest request) { @@ -111,114 +97,49 @@ class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwa void handleAttachment(GrpcAttachment attachment) { if (attachment.hasFile()) { - setCurrentMetadata(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); + attachmentCollector = buildContentCollector(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); groupName = attachment.getFile().getGroupName(); } else { - handleFileContent(attachment.getContent()); + if (Objects.isNull(attachmentCollector)) { + throw new IllegalStateException("File content received before metadata."); + } + attachmentCollector.collect(attachment.getContent()).ifPresent(this::addAsAttachment); } } void handleRepresentation(GrpcRepresentation representation) { if (representation.hasFile()) { - setCurrentMetadata(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); + representationCollector = buildContentCollector(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); } else { - handleFileContent(representation.getContent()); - } - - } - - void setCurrentMetadata(IncomingFile metaData) { - if (Objects.nonNull(currentFile)) { - throw new IllegalStateException("Received additional file before previous file reached the end."); - } - currentFile = metaData; - } - - void handleFileContent(GrpcFileContent fileContent) { - if (Objects.isNull(receivingFileContent)) { - initContentReceiving(); - } - storeFileContent(fileContent); - } - - void initContentReceiving() { - try { - pipedInput = new PipedInputStream(CHUNK_SIZE); - pipedOutput = new PipedOutputStream(pipedInput); - receivingFileContent = fileSaver.apply(pipedInput); - } catch (IOException e) { - throw new TechnicalException("Upload initialization failed", e); - } - } - - void storeFileContent(GrpcFileContent content) { - if (Objects.isNull(currentFile)) { - throw new IllegalStateException("File content received before metadata."); - } - if (content.getIsEndOfFile()) { - handleEndOfFile(); - } else { - try { - pipedOutput.write(content.getContent().toByteArray()); - } catch (IOException e) { - throw new TechnicalException("Error when writing file content.", e); + if (Objects.isNull(representationCollector)) { + throw new IllegalStateException("File content received before metadata."); } + representationCollector.collect(representation.getContent()).ifPresent(this::addAsRepresentation); } } - void handleEndOfFile() { - closeOutputPipe(); - var completedIncomingFile = currentFile.toBuilder().file(getSavedFileContent()).build(); - if (Objects.isNull(groupName)) { - addAsRepresentation(completedIncomingFile); - } else { - addAsAttachment(completedIncomingFile); - } - resetFileReceiving(); - } - - private void addAsRepresentation(IncomingFile completedIncomingFile) { - representations.add(completedIncomingFile); + private ContentCollector buildContentCollector(IncomingFile incomingFile) { + return ContentCollector.builder() + .fileSaver(fileSaver) + .incomingFile(incomingFile) + .build(); } - private void addAsAttachment(IncomingFile completedIncomingFile) { + void addAsAttachment(IncomingFile completedIncomingFile) { attachments.computeIfAbsent(groupName, s -> new ArrayList<>()).add(completedIncomingFile); + attachmentCollector = null; } - File getSavedFileContent() { - try { - return receivingFileContent.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); - } catch (ExecutionException | TimeoutException e) { - throw new TechnicalException("Receiving file failed.", e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new TechnicalException("Upload was interrupted.", e); - } finally { - closeInputPipe(); - } - } - - void resetFileReceiving() { - currentFile = null; - groupName = null; - pipedOutput = null; - pipedInput = null; - receivingFileContent = null; + void addAsRepresentation(IncomingFile completedIncomingFile) { + representations.add(completedIncomingFile); + representationCollector = null; } @Override public synchronized void onError(Throwable t) { LOG.error("Error happened. Receiving stream closed.", t); - closeOutputPipe(); - closeInputPipe(); - } - - void closeOutputPipe() { - IOUtils.closeQuietly(pipedOutput, e -> LOG.error("Cannot close output stream.", e)); - } - - void closeInputPipe() { - IOUtils.closeQuietly(pipedInput, e -> LOG.error("Cannot close input stream.", e)); + attachmentCollector.close(); + representationCollector.close(); } @Override diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/ContentCollectorTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/ContentCollectorTest.java new file mode 100644 index 000000000..4385eb7ef --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/ContentCollectorTest.java @@ -0,0 +1,484 @@ +/* + * Copyright (C) 2025 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.eingang.forwarder; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; +import java.util.function.Function; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.test.util.ReflectionTestUtils; + +import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.forwarding.GrpcFileContent; +import lombok.SneakyThrows; + +class ContentCollectorTest { + + private ContentCollector contentCollector; + @Mock + private Function<InputStream, CompletableFuture<File>> fileSaver; + @Mock + private CompletableFuture<File> fileContentFuture; + private final IncomingFile incomingFile = IncomingFileTestFactory.createBuilder().file(null).build(); + + void setUpContentCollector() { + when(fileSaver.apply(any())).thenReturn(fileContentFuture); + contentCollector = spy(ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build()); + } + + @Nested + class TestBuilding { + + private final byte[] content = new byte[] { 1, 2, 3 }; + + @Test + void shouldSetIncomingFile() { + setUpContentCollector(); + + assertThat(getIncomingFile()).isSameAs(incomingFile); + } + + @Test + void shouldCreateInputStream() { + setUpContentCollector(); + + assertThat(getPipedInput()).isNotNull(); + } + + @Test + void shouldCreateOutputStream() { + setUpContentCollector(); + + assertThat(getPipedOutput()).isNotNull(); + } + + @Test + void shouldCreateConnectedStreams() { + setUpContentCollector(); + + verifyStreamSetUp(); + } + + @SneakyThrows + private void verifyStreamSetUp() { + var pipedInput = getPipedInput(); + var pipedOutput = getPipedOutput(); + pipedOutput.write(content); + pipedOutput.close(); + var readBytes = pipedInput.readAllBytes(); + assertThat(readBytes).isEqualTo(content); + } + + @Test + void shouldCallFileSaver() { + setUpContentCollector(); + + verify(fileSaver).apply(getPipedInput()); + } + + @Test + void shouldSetReceivingFileContent() { + setUpContentCollector(); + + assertThat(getFileContent()).isSameAs(fileContentFuture); + } + } + + @Nested + class TestCollect { + + @Mock + private PipedOutputStream pipedOutput; + + @BeforeEach + void setUp() { + setUpContentCollector(); + setPipedOutput(pipedOutput); + } + + @Nested + class TestOnEndOfFile { + + private final GrpcFileContent fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(true).build(); + private final IncomingFile completedIncomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void setUp() { + doReturn(completedIncomingFile).when(contentCollector).handleEndOfFile(); + } + + @Test + void shouldCallHandleEndOfFile() { + contentCollector.collect(fileContent); + + verify(contentCollector).handleEndOfFile(); + } + + @Test + @SneakyThrows + void shouldNotWriteContentToOutputStream() { + contentCollector.collect(fileContent); + + verify(pipedOutput, never()).write(any()); + } + + @Test + void shouldReturnCompletedIncomingFile() { + var result = contentCollector.collect(fileContent); + + assertThat(result).contains(completedIncomingFile); + } + } + + @Nested + class TestOnNotEndOfFile { + + private final GrpcFileContent fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(false).build(); + + @Test + @SneakyThrows + void shouldWriteContentToOutputStream() { + contentCollector.collect(fileContent); + + verify(pipedOutput).write(GrpcFileContentTestFactory.CONTENT); + } + + @Test + void shouldNotCallHandleEndOfFile() { + contentCollector.collect(fileContent); + + verify(contentCollector, never()).handleEndOfFile(); + } + + @Test + void shouldReturnEmpty() { + var result = contentCollector.collect(fileContent); + + assertThat(result).isEmpty(); + } + + @Test + @SneakyThrows + void shouldThrowTechnicalExceptionOnIOException() { + doThrow(new IOException()).when(pipedOutput).write(any()); + + assertThrows(TechnicalException.class, () -> { + contentCollector.collect(fileContent); + }); + } + } + } + + @Nested + class TestHandleEndOfFile { + + @BeforeEach + void setUp() { + setUpContentCollector(); + doNothing().when(contentCollector).closeOutputPipe(); + doReturn(IncomingFileTestFactory.FILE).when(contentCollector).getSavedFileContent(); + } + + @Test + void shouldCallCloseOutputPipe() { + contentCollector.handleEndOfFile(); + + verify(contentCollector).closeOutputPipe(); + } + + @Test + void shouldCallGetSavedFileContent() { + contentCollector.handleEndOfFile(); + + verify(contentCollector).getSavedFileContent(); + } + + @Test + void shouldReturnIncomingFileWithSavedFile() { + var returnedIncomingFile = contentCollector.handleEndOfFile(); + + assertThat(returnedIncomingFile).usingRecursiveComparison().isEqualTo(IncomingFileTestFactory.create()); + } + } + + @Nested + class TestGetSavedFileContent { + @BeforeEach + void setUp() { + setUpContentCollector(); + doNothing().when(contentCollector).closeInputPipe(); + } + + @Nested + class TestOnNoExceptions { + @Mock + private File fileContent; + + @BeforeEach + @SneakyThrows + void setUp() { + when(fileContentFuture.get(anyLong(), any())).thenReturn(fileContent); + } + + @Test + void shouldReturnFile() { + var savedFileContent = contentCollector.getSavedFileContent(); + + assertThat(savedFileContent).isSameAs(fileContent); + } + + @Test + void shouldCallCloseInputPipe() { + contentCollector.getSavedFileContent(); + + verify(contentCollector).closeInputPipe(); + } + } + + @Nested + class TestOnExecutionException { + + @BeforeEach + void setUp() { + setFileContent(CompletableFuture.failedFuture(new Exception())); + } + + @Test + void shouldThrowTechnicalException() { + assertThrows(TechnicalException.class, () -> contentCollector.getSavedFileContent()); + } + + @Test + void shouldCallCloseInputPipe() { + try { + contentCollector.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + verify(contentCollector).closeInputPipe(); + } + } + + @Nested + class TestOnTimeoutException { + + @Mock + private CompletableFuture<File> fileFuture; + + @BeforeEach + @SneakyThrows + void setUp() { + setFileContent(fileFuture); + when(fileFuture.get(anyLong(), any())).thenThrow(new TimeoutException()); + } + + @Test + void shouldThrowTechnicalException() { + assertThrows(TechnicalException.class, () -> contentCollector.getSavedFileContent()); + } + + @Test + void shouldCallCloseInputPipe() { + try { + contentCollector.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + verify(contentCollector).closeInputPipe(); + } + } + + @Nested + class TestOnInterruptedException { + + @Mock + private CompletableFuture<File> fileFuture; + + @BeforeEach + @SneakyThrows + void setUp() { + setFileContent(fileFuture); + when(fileFuture.get(anyLong(), any())).thenThrow(new InterruptedException()); + } + + @Test + void shouldThrowTechnicalException() { + assertThrows(TechnicalException.class, () -> contentCollector.getSavedFileContent()); + } + + @Test + void shouldInterruptCurrentThread() { + try { + contentCollector.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + assertThat(Thread.currentThread().isInterrupted()).isTrue(); + } + + @Test + void shouldCallCloseInputPipe() { + try { + contentCollector.getSavedFileContent(); + } catch (TechnicalException e) { + // expected + } + + verify(contentCollector).closeInputPipe(); + } + } + } + + @Nested + class TestClose { + + @BeforeEach + void setUp() { + setUpContentCollector(); + doNothing().when(contentCollector).closeOutputPipe(); + doNothing().when(contentCollector).closeInputPipe(); + } + + @Test + void shouldCallCloseOutputPipe() { + contentCollector.close(); + + verify(contentCollector).closeOutputPipe(); + } + + @Test + void shouldCallCloseInputPipe() { + contentCollector.close(); + + verify(contentCollector).closeInputPipe(); + } + } + + @Nested + class TestCloseOutputPipe { + + @Mock + private PipedOutputStream pipedOutput; + + @BeforeEach + void setUp() { + setUpContentCollector(); + setPipedOutput(pipedOutput); + } + + @Test + @SneakyThrows + void shouldClosePipedOutput() { + contentCollector.closeOutputPipe(); + + verify(pipedOutput).close(); + } + + @Test + @SneakyThrows + void shouldNotThrowException() { + doThrow(IOException.class).when(pipedOutput).close(); + + assertDoesNotThrow(() -> contentCollector.closeOutputPipe()); + } + } + + @Nested + class TestCloseInputPipe { + + @Mock + private PipedInputStream pipedInput; + + @BeforeEach + void setUp() { + setUpContentCollector(); + setPipedInput(pipedInput); + } + + @Test + @SneakyThrows + void shouldClosePipedInput() { + contentCollector.closeInputPipe(); + + verify(pipedInput).close(); + } + + @Test + @SneakyThrows + void shouldNotThrowException() { + doThrow(IOException.class).when(pipedInput).close(); + + assertDoesNotThrow(() -> contentCollector.closeInputPipe()); + } + } + + @SuppressWarnings("unchecked") + private CompletableFuture<File> getFileContent() { + return (CompletableFuture<File>) ReflectionTestUtils.getField(contentCollector, "receivingFileContent"); + } + + private void setFileContent(CompletableFuture<File> fileContent) { + ReflectionTestUtils.setField(contentCollector, "receivingFileContent", fileContent); + } + + private PipedInputStream getPipedInput() { + return (PipedInputStream) ReflectionTestUtils.getField(contentCollector, "pipedInput"); + } + + private void setPipedInput(PipedInputStream pipedInput) { + ReflectionTestUtils.setField(contentCollector, "pipedInput", pipedInput); + } + + private PipedOutputStream getPipedOutput() { + return (PipedOutputStream) ReflectionTestUtils.getField(contentCollector, "pipedOutput"); + } + + private void setPipedOutput(PipedOutputStream pipedOutput) { + ReflectionTestUtils.setField(contentCollector, "pipedOutput", pipedOutput); + } + + private IncomingFile getIncomingFile() { + return (IncomingFile) ReflectionTestUtils.getField(contentCollector, "incomingFile"); + } + +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java index 04d21376b..f312ec86f 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -29,14 +29,11 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.File; -import java.io.IOException; import java.io.InputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Function; @@ -46,18 +43,15 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.springframework.test.util.ReflectionTestUtils; -import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.forwarding.GrpcAttachment; -import de.ozgcloud.eingang.forwarding.GrpcFileContent; import de.ozgcloud.eingang.forwarding.GrpcRepresentation; import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; -import lombok.SneakyThrows; class EingangStubReceiverStreamObserverTest { @@ -204,6 +198,14 @@ class EingangStubReceiverStreamObserverTest { @Nested class TestHandleAttachment { + @Mock + private ContentCollector attachmentCollector; + + @BeforeEach + void setUp() { + setAttachmentCollector(attachmentCollector); + } + @Nested class TestWithFile { @@ -212,7 +214,6 @@ class EingangStubReceiverStreamObserverTest { @BeforeEach void mock() { - doNothing().when(observer).setCurrentMetadata(any()); when(incomingFileMapper.fromGrpcAttachmentFile(any())).thenReturn(incomingFile); } @@ -224,10 +225,13 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldCallSetCurrentMetadata() { + void shouldSetAttachmentCollector() { + var expectedContentCollector = ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build(); + observer.handleAttachment(attachmentWithFile); - verify(observer).setCurrentMetadata(incomingFile); + assertThat(getAttachmentCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") + .isEqualTo(expectedContentCollector); } @Test @@ -238,10 +242,10 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldNotCallHandleFileContent() { + void shouldNotCollectContent() { observer.handleAttachment(attachmentWithFile); - verify(observer, never()).handleFileContent(any()); + verify(attachmentCollector, never()).collect(any()); } } @@ -249,17 +253,13 @@ class EingangStubReceiverStreamObserverTest { class TestWithContent { private final GrpcAttachment attachmentWithContent = GrpcAttachmentTestFactory.createWithContent(); - - @BeforeEach - void mock() { - doNothing().when(observer).handleFileContent(any()); - } + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @Test - void shouldCallHandleFileContent() { + void shouldCollectContent() { observer.handleAttachment(attachmentWithContent); - verify(observer).handleFileContent(GrpcAttachmentTestFactory.CONTENT); + verify(attachmentCollector).collect(GrpcAttachmentTestFactory.CONTENT); } @Test @@ -275,12 +275,38 @@ class EingangStubReceiverStreamObserverTest { assertThat(getGroupName()).isNull(); } + + @Test + void shouldCallAddAsAttachment() { + when(attachmentCollector.collect(any())).thenReturn(Optional.of(incomingFile)); + + observer.handleAttachment(attachmentWithContent); + + verify(observer).addAsAttachment(incomingFile); + } + + @Test + void shouldNotCallAddAsAttachment() { + when(attachmentCollector.collect(any())).thenReturn(Optional.empty()); + + observer.handleAttachment(attachmentWithContent); + + verify(observer, never()).addAsAttachment(any()); + } } } @Nested class TestHandleRepresentation { + @Mock + private ContentCollector representationCollector; + + @BeforeEach + void setUp() { + setRepresentationCollector(representationCollector); + } + @Nested class TestWithFile { @@ -289,7 +315,6 @@ class EingangStubReceiverStreamObserverTest { @BeforeEach void mock() { - doNothing().when(observer).setCurrentMetadata(any()); when(incomingFileMapper.fromGrpcRepresentationFile(any())).thenReturn(incomingFile); } @@ -301,17 +326,20 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldCallSetCurrentMetadata() { + void shouldSetRepresentationCollector() { + var expectedContentCollector = ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build(); + observer.handleRepresentation(representationWithFile); - verify(observer).setCurrentMetadata(incomingFile); + assertThat(getRepresentationCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") + .isEqualTo(expectedContentCollector); } @Test - void shouldNotCallHandleFileContent() { + void shouldNotCollectContent() { observer.handleRepresentation(representationWithFile); - verify(observer, never()).handleFileContent(any()); + verify(representationCollector, never()).collect(any()); } } @@ -319,17 +347,13 @@ class EingangStubReceiverStreamObserverTest { class TestWithContent { private final GrpcRepresentation representationWithContent = GrpcRepresentationTestFactory.createWithContent(); - - @BeforeEach - void mock() { - doNothing().when(observer).handleFileContent(any()); - } + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @Test - void shouldCallHandleFileContent() { + void shouldCollectContent() { observer.handleRepresentation(representationWithContent); - verify(observer).handleFileContent(GrpcRepresentationTestFactory.CONTENT); + verify(representationCollector).collect(GrpcRepresentationTestFactory.CONTENT); } @Test @@ -338,549 +362,111 @@ class EingangStubReceiverStreamObserverTest { verify(incomingFileMapper, never()).fromGrpcRepresentationFile(any()); } - } - } - - @Nested - class TestSetCurrentMetadata { - - private final IncomingFile incomingFile = IncomingFileTestFactory.create(); - - @Test - void shouldThrowIllegalStateExceptionIfCurrentFileIsSet() { - setCurrentFile(incomingFile); - - assertThrows(IllegalStateException.class, () -> observer.setCurrentMetadata(incomingFile)); - } - - @Test - void shouldSetCurrentFile() { - observer.setCurrentMetadata(incomingFile); - - assertThat(getCurrentFile()).isSameAs(incomingFile); - } - } - - @Nested - class TestHandleFileContent { - - private final GrpcFileContent fileContent = GrpcFileContentTestFactory.create(); - - @Nested - class TestOnReceivingFileContentIsNull { - @BeforeEach - void mock() { - doNothing().when(observer).initContentReceiving(); - doNothing().when(observer).storeFileContent(any()); - } - - @Test - void shouldCallInitContentReceiving() { - observer.handleFileContent(fileContent); - - verify(observer).initContentReceiving(); - } @Test - void shouldCallStoreFileContent() { - observer.handleFileContent(fileContent); - - verify(observer).storeFileContent(fileContent); - } - } - - @Nested - class TestOnReceivingFileContentIsNotNull { - @Mock - private CompletableFuture<File> receivingFileContent; + void shouldCallAddAsRepresentation() { + when(representationCollector.collect(any())).thenReturn(Optional.of(incomingFile)); - @BeforeEach - void mock() { - doNothing().when(observer).storeFileContent(any()); - setFileContent(receivingFileContent); - } - - @Test - void shouldNotCallInitContentReceiving() { - observer.handleFileContent(fileContent); - - verify(observer, never()).initContentReceiving(); - } - - @Test - void shouldCallStoreFileContent() { - observer.handleFileContent(fileContent); + observer.handleRepresentation(representationWithContent); - verify(observer).storeFileContent(fileContent); + verify(observer).addAsRepresentation(incomingFile); } - } - } - - @Nested - class TestInitContentReceiving { - - private final byte[] content = new byte[] { 1, 2, 3 }; - - @Test - void shouldCreateInputStream() { - observer.initContentReceiving(); - - assertThat(getPipedInput()).isNotNull(); - } - - @Test - void shouldCreateOutputStream() { - observer.initContentReceiving(); - - assertThat(getPipedOutput()).isNotNull(); - } - - @Test - void shouldCreateConnectedStreams() { - observer.initContentReceiving(); - - verifyStreamSetUp(); - } - - @SneakyThrows - private void verifyStreamSetUp() { - var pipedInput = getPipedInput(); - var pipedOutput = getPipedOutput(); - pipedOutput.write(content); - pipedOutput.close(); - var readBytes = pipedInput.readAllBytes(); - assertThat(readBytes).isEqualTo(content); - } - - @Test - void shouldCallFileSaver() { - observer.initContentReceiving(); - - verify(fileSaver).apply(getPipedInput()); - } - - @Test - void shouldSetReceivingFileContent() { - var fileFuture = CompletableFuture.completedFuture(mock(File.class)); - when(fileSaver.apply(any())).thenReturn(fileFuture); - - observer.initContentReceiving(); - - assertThat(getFileContent()).isSameAs(fileFuture); - } - } - - @Nested - class TestStoreFileContent { - @Mock - private PipedOutputStream pipedOutput; - - @BeforeEach - void setUp() { - setPipedOutput(pipedOutput); - } - - @Nested - class TestOnCurrentFileIsNull { @Test - void shouldThrowTechnicalException() { - var fileContent = GrpcFileContentTestFactory.create(); + void shouldNotCallAddAsRepresentation() { + when(representationCollector.collect(any())).thenReturn(Optional.empty()); - assertThrows(IllegalStateException.class, () -> observer.storeFileContent(fileContent)); - } - } - - @Nested - class TestOnCurrentFileIsNotNull { - - private final IncomingFile incomingFile = IncomingFileTestFactory.create(); - - @BeforeEach - void mock() { - setCurrentFile(incomingFile); - } - - @Nested - class TestOnEndOfFile { - - private GrpcFileContent fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(true).build(); - - @BeforeEach - void setUp() { - doNothing().when(observer).handleEndOfFile(); - } - - @Test - void shouldCallHandleEndOfFile() { - observer.storeFileContent(fileContent); - - verify(observer).handleEndOfFile(); - } - - @Test - @SneakyThrows - void shouldNotWriteContentToOutputStream() { - observer.storeFileContent(fileContent); - - verify(pipedOutput, never()).write(any()); - } - } - - @Nested - class TestOnNotEndOfFile { - - private GrpcFileContent fileContent = GrpcFileContentTestFactory.createBuilder().setIsEndOfFile(false).build(); - - @Test - @SneakyThrows - void shouldWriteContentToOutputStream() { - observer.storeFileContent(fileContent); - - verify(pipedOutput).write(GrpcFileContentTestFactory.CONTENT); - } - - @Test - void shouldNotCallHandleEndOfFile() { - observer.storeFileContent(fileContent); - - verify(observer, never()).handleEndOfFile(); - } - - @Test - @SneakyThrows - void shouldThrowTechnicalExceptionOnIOException() { - doThrow(new IOException()).when(pipedOutput).write(any()); + observer.handleRepresentation(representationWithContent); - assertThrows(TechnicalException.class, () -> { - observer.storeFileContent(fileContent); - }); - } + verify(observer, never()).addAsRepresentation(any()); } } } @Nested - class TestHandleEndOfFile { + class TestAddAsAttachment { @Mock - private File savedFileContent; + private ContentCollector attachmentCollector; - private final IncomingFile incomingFile = IncomingFileTestFactory.createBuilder().file(null).build(); + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @BeforeEach void setUp() { - doNothing().when(observer).closeOutputPipe(); - doReturn(savedFileContent).when(observer).getSavedFileContent(); - setCurrentFile(incomingFile); + setRepresentationCollector(attachmentCollector); + setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); } @Test - void shouldCallCloseOutputPipe() { - observer.handleEndOfFile(); - - verify(observer).closeOutputPipe(); - } - - @Nested - class TestOnGroupNameNull { - - @BeforeEach - void setUp() { - setGroupName(null); - } - - @Test - void shouldAddFileToRepresentations() { - var expectedIncomingFile = IncomingFileTestFactory.createBuilder().file(savedFileContent).build(); + void shouldAddFileToAttachments() { + observer.addAsAttachment(incomingFile); - observer.handleEndOfFile(); - - assertThat(getRepresentations()).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedIncomingFile); - } - } - - @Nested - class TestOnGroupNameSet { - - @BeforeEach - void setUp() { - setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); - } - - @Test - void shouldAddFileToAttachments() { - var expectedIncomingFile = IncomingFileTestFactory.createBuilder().file(savedFileContent).build(); - - observer.handleEndOfFile(); - - var attachmentGroup = getAttachments().get(GrpcAttachmentFileTestFactory.GROUP_NAME); - assertThat(attachmentGroup).usingRecursiveFieldByFieldElementComparator().containsExactly(expectedIncomingFile); - } + var attachmentGroup = getAttachments().get(GrpcAttachmentFileTestFactory.GROUP_NAME); + assertThat(attachmentGroup).usingRecursiveFieldByFieldElementComparator().containsExactly(incomingFile); } @Test - void shouldCallResetFileReceiving() { - observer.handleEndOfFile(); + void shouldSetAttachmentCollectorToNull() { + observer.addAsAttachment(incomingFile); - verify(observer).resetFileReceiving(); + assertThat(getAttachmentCollector()).isNull(); } } @Nested - class TestGetSavedFileContent { - @BeforeEach - void setUp() { - doNothing().when(observer).closeInputPipe(); - } + class TestAddAsRepresentation { - @Nested - class TestOnNoExceptions { - @Mock - private File fileContent; - - @BeforeEach - void setUp() { - setFileContent(CompletableFuture.completedFuture(fileContent)); - } - - @Test - void shouldReturnFile() { - var savedFileContent = observer.getSavedFileContent(); - - assertThat(savedFileContent).isSameAs(fileContent); - } - - @Test - void shouldCallCloseInputPipe() { - observer.getSavedFileContent(); - - verify(observer).closeInputPipe(); - } - } - - @Nested - class TestOnExecutionException { - - @BeforeEach - void setUp() { - setFileContent(CompletableFuture.failedFuture(new Exception())); - } - - @Test - void shouldThrowTechnicalException() { - assertThrows(TechnicalException.class, () -> observer.getSavedFileContent()); - } - - @Test - void shouldCallCloseInputPipe() { - try { - observer.getSavedFileContent(); - } catch (TechnicalException e) { - // expected - } - - verify(observer).closeInputPipe(); - } - } - - @Nested - class TestOnTimeoutException { - - @Mock - private CompletableFuture<File> fileFuture; - - @BeforeEach - @SneakyThrows - void setUp() { - setFileContent(fileFuture); - when(fileFuture.get(anyLong(), any())).thenThrow(new TimeoutException()); - } - - @Test - void shouldThrowTechnicalException() { - assertThrows(TechnicalException.class, () -> observer.getSavedFileContent()); - } - - @Test - void shouldCallCloseInputPipe() { - try { - observer.getSavedFileContent(); - } catch (TechnicalException e) { - // expected - } - - verify(observer).closeInputPipe(); - } - } - - @Nested - class TestOnInterruptedException { - - @Mock - private CompletableFuture<File> fileFuture; - - @BeforeEach - @SneakyThrows - void setUp() { - setFileContent(fileFuture); - when(fileFuture.get(anyLong(), any())).thenThrow(new InterruptedException()); - } - - @Test - void shouldThrowTechnicalException() { - assertThrows(TechnicalException.class, () -> observer.getSavedFileContent()); - } - - @Test - void shouldInterruptCurrentThread() { - try { - observer.getSavedFileContent(); - } catch (TechnicalException e) { - // expected - } - - assertThat(Thread.currentThread().isInterrupted()).isTrue(); - } - - @Test - void shouldCallCloseInputPipe() { - try { - observer.getSavedFileContent(); - } catch (TechnicalException e) { - // expected - } - - verify(observer).closeInputPipe(); - } - } - } + @Mock + private ContentCollector representationCollector; - @Nested - class TestResetFielReceiving { + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @BeforeEach void setUp() { - setCurrentFile(IncomingFileTestFactory.create()); - setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); - setPipedOutput(mock(PipedOutputStream.class)); - setPipedOutput(mock(PipedOutputStream.class)); - setFileContent(CompletableFuture.completedFuture(mock(File.class))); - } - - @Test - void shouldResetCurrentFile() { - observer.resetFileReceiving(); - - assertThat(getCurrentFile()).isNull(); - } - - @Test - void shouldResetGroupName() { - observer.resetFileReceiving(); - - assertThat(getGroupName()).isNull(); - } - - @Test - void shouldResetPipedOutput() { - observer.resetFileReceiving(); - - assertThat(getPipedOutput()).isNull(); + setRepresentationCollector(representationCollector); } @Test - void shouldResetPipedInput() { - observer.resetFileReceiving(); + void shouldAddFileToRepresentations() { + observer.addAsRepresentation(incomingFile); - assertThat(getPipedInput()).isNull(); + assertThat(getRepresentations()).usingRecursiveFieldByFieldElementComparator().containsExactly(incomingFile); } @Test - void shouldResetReceivingFileContent() { - observer.resetFileReceiving(); + void shouldSetRepresentationCollectorToNull() { + observer.addAsRepresentation(incomingFile); - assertThat(getFileContent()).isNull(); + assertThat(getRepresentationCollector()).isNull(); } } @Nested class TestOnError { - @BeforeEach - void mock() { - doNothing().when(observer).closeOutputPipe(); - doNothing().when(observer).closeInputPipe(); - } - - @Test - void shouldCallCloseOutputPipe() { - observer.onError(new Exception()); - - verify(observer).closeOutputPipe(); - } - - @Test - void shouldCallCloseInputPipe() { - observer.onError(new Exception()); - - verify(observer).closeInputPipe(); - } - } - - @Nested - class TestCloseOutputPipe { - @Mock - private PipedOutputStream pipedOutput; - - @BeforeEach - void setUp() { - setPipedOutput(pipedOutput); - } - - @Test - @SneakyThrows - void shouldClosePipedOutput() { - observer.closeOutputPipe(); - - verify(pipedOutput).close(); - } - - @Test - @SneakyThrows - void shouldNotThrowException() { - doThrow(IOException.class).when(pipedOutput).close(); - - assertDoesNotThrow(() -> observer.closeOutputPipe()); - } - } - - @Nested - class TestCloseInputPipe { - + private ContentCollector attachmentCollector; @Mock - private PipedInputStream pipedInput; + private ContentCollector representationCollector; @BeforeEach - void setUp() { - setPipedInput(pipedInput); + void mock() { + setAttachmentCollector(attachmentCollector); + setRepresentationCollector(representationCollector); } @Test - @SneakyThrows - void shouldClosePipedInput() { - observer.closeInputPipe(); + void shouldCloseAttachmentCollector() { + observer.onError(new Exception()); - verify(pipedInput).close(); + verify(attachmentCollector).close(); } @Test - @SneakyThrows - void shouldNotThrowException() { - doThrow(IOException.class).when(pipedInput).close(); + void shouldCloseRepresentationCollector() { + observer.onError(new Exception()); - assertDoesNotThrow(() -> observer.closeInputPipe()); + verify(representationCollector).close(); } } @@ -987,39 +573,6 @@ class EingangStubReceiverStreamObserverTest { ReflectionTestUtils.setField(observer, "groupName", groupName); } - private IncomingFile getCurrentFile() { - return (IncomingFile) ReflectionTestUtils.getField(observer, "currentFile"); - } - - private void setCurrentFile(IncomingFile incomingFile) { - ReflectionTestUtils.setField(observer, "currentFile", incomingFile); - } - - private void setFileContent(CompletableFuture<File> fileFuture) { - ReflectionTestUtils.setField(observer, "receivingFileContent", fileFuture); - } - - @SuppressWarnings("unchecked") - private CompletableFuture<File> getFileContent() { - return (CompletableFuture<File>) ReflectionTestUtils.getField(observer, "receivingFileContent"); - } - - private PipedInputStream getPipedInput() { - return (PipedInputStream) ReflectionTestUtils.getField(observer, "pipedInput"); - } - - private void setPipedInput(PipedInputStream pipedInput) { - ReflectionTestUtils.setField(observer, "pipedInput", pipedInput); - } - - private PipedOutputStream getPipedOutput() { - return (PipedOutputStream) ReflectionTestUtils.getField(observer, "pipedOutput"); - } - - private void setPipedOutput(PipedOutputStream pipedOutput) { - ReflectionTestUtils.setField(observer, "pipedOutput", pipedOutput); - } - @SuppressWarnings("unchecked") private List<IncomingFile> getRepresentations() { return (List<IncomingFile>) ReflectionTestUtils.getField(observer, "representations"); @@ -1038,4 +591,20 @@ class EingangStubReceiverStreamObserverTest { ReflectionTestUtils.setField(observer, "attachments", attachments); } + private ContentCollector getAttachmentCollector() { + return (ContentCollector) ReflectionTestUtils.getField(observer, "attachmentCollector"); + } + + private void setAttachmentCollector(ContentCollector attachmentCollector) { + ReflectionTestUtils.setField(observer, "attachmentCollector", attachmentCollector); + } + + private ContentCollector getRepresentationCollector() { + return (ContentCollector) ReflectionTestUtils.getField(observer, "representationCollector"); + } + + private void setRepresentationCollector(ContentCollector representationCollector) { + ReflectionTestUtils.setField(observer, "representationCollector", representationCollector); + } + } -- GitLab From 9abbd56222cb1db5a0a40e8a968fe6a59d16e567 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Fri, 21 Mar 2025 09:17:59 +0100 Subject: [PATCH 26/28] OZG-7573 refactor EingangStubReceiverStreamObserver --- .../EingangStubReceiverStreamObserver.java | 40 +++-- ...EingangStubReceiverStreamObserverTest.java | 164 +++++++++++------- 2 files changed, 129 insertions(+), 75 deletions(-) diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java index 45f253538..40dbc1b1a 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -72,8 +72,7 @@ class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwa private final Map<String, List<IncomingFile>> attachments = new HashMap<>(); private String groupName; - private ContentCollector attachmentCollector; - private ContentCollector representationCollector; + private ContentCollector contentCollector; @Override public synchronized void onNext(GrpcRouteForwardingRequest request) { @@ -97,24 +96,28 @@ class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwa void handleAttachment(GrpcAttachment attachment) { if (attachment.hasFile()) { - attachmentCollector = buildContentCollector(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); + verifyNoOngoingFileDownload(); + contentCollector = buildContentCollector(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); groupName = attachment.getFile().getGroupName(); } else { - if (Objects.isNull(attachmentCollector)) { - throw new IllegalStateException("File content received before metadata."); - } - attachmentCollector.collect(attachment.getContent()).ifPresent(this::addAsAttachment); + verifyMetadataWasSent(); + contentCollector.collect(attachment.getContent()).ifPresent(this::addAsAttachment); } } void handleRepresentation(GrpcRepresentation representation) { if (representation.hasFile()) { - representationCollector = buildContentCollector(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); + verifyNoOngoingFileDownload(); + contentCollector = buildContentCollector(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); } else { - if (Objects.isNull(representationCollector)) { - throw new IllegalStateException("File content received before metadata."); - } - representationCollector.collect(representation.getContent()).ifPresent(this::addAsRepresentation); + verifyMetadataWasSent(); + contentCollector.collect(representation.getContent()).ifPresent(this::addAsRepresentation); + } + } + + void verifyNoOngoingFileDownload() { + if (Objects.nonNull(contentCollector)) { + throw new IllegalStateException("File metadata received before previous file content was completed."); } } @@ -125,21 +128,26 @@ class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwa .build(); } + void verifyMetadataWasSent() { + if (Objects.isNull(contentCollector)) { + throw new IllegalStateException("File content received before metadata."); + } + } + void addAsAttachment(IncomingFile completedIncomingFile) { attachments.computeIfAbsent(groupName, s -> new ArrayList<>()).add(completedIncomingFile); - attachmentCollector = null; + contentCollector = null; } void addAsRepresentation(IncomingFile completedIncomingFile) { representations.add(completedIncomingFile); - representationCollector = null; + contentCollector = null; } @Override public synchronized void onError(Throwable t) { LOG.error("Error happened. Receiving stream closed.", t); - attachmentCollector.close(); - representationCollector.close(); + contentCollector.close(); } @Override diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java index f312ec86f..c8e6dce6b 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -199,12 +199,7 @@ class EingangStubReceiverStreamObserverTest { class TestHandleAttachment { @Mock - private ContentCollector attachmentCollector; - - @BeforeEach - void setUp() { - setAttachmentCollector(attachmentCollector); - } + private ContentCollector contentCollector; @Nested class TestWithFile { @@ -213,8 +208,16 @@ class EingangStubReceiverStreamObserverTest { private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @BeforeEach - void mock() { + void initMock() { when(incomingFileMapper.fromGrpcAttachmentFile(any())).thenReturn(incomingFile); + doNothing().when(observer).verifyNoOngoingFileDownload(); + } + + @Test + void shouldCallVerifyNoOngoingFileDownload() { + observer.handleAttachment(attachmentWithFile); + + verify(observer).verifyNoOngoingFileDownload(); } @Test @@ -225,12 +228,12 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldSetAttachmentCollector() { + void shouldSetContentCollector() { var expectedContentCollector = ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build(); observer.handleAttachment(attachmentWithFile); - assertThat(getAttachmentCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") + assertThat(getContentCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") .isEqualTo(expectedContentCollector); } @@ -245,7 +248,7 @@ class EingangStubReceiverStreamObserverTest { void shouldNotCollectContent() { observer.handleAttachment(attachmentWithFile); - verify(attachmentCollector, never()).collect(any()); + verify(contentCollector, never()).collect(any()); } } @@ -255,11 +258,23 @@ class EingangStubReceiverStreamObserverTest { private final GrpcAttachment attachmentWithContent = GrpcAttachmentTestFactory.createWithContent(); private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + @BeforeEach + void setUp() { + setContentCollector(contentCollector); + } + + @Test + void shouldCallVerifyMetadataWasSent() { + observer.handleAttachment(attachmentWithContent); + + verify(observer).verifyMetadataWasSent(); + } + @Test void shouldCollectContent() { observer.handleAttachment(attachmentWithContent); - verify(attachmentCollector).collect(GrpcAttachmentTestFactory.CONTENT); + verify(contentCollector).collect(GrpcAttachmentTestFactory.CONTENT); } @Test @@ -278,7 +293,7 @@ class EingangStubReceiverStreamObserverTest { @Test void shouldCallAddAsAttachment() { - when(attachmentCollector.collect(any())).thenReturn(Optional.of(incomingFile)); + when(contentCollector.collect(any())).thenReturn(Optional.of(incomingFile)); observer.handleAttachment(attachmentWithContent); @@ -287,12 +302,13 @@ class EingangStubReceiverStreamObserverTest { @Test void shouldNotCallAddAsAttachment() { - when(attachmentCollector.collect(any())).thenReturn(Optional.empty()); + when(contentCollector.collect(any())).thenReturn(Optional.empty()); observer.handleAttachment(attachmentWithContent); verify(observer, never()).addAsAttachment(any()); } + } } @@ -300,12 +316,7 @@ class EingangStubReceiverStreamObserverTest { class TestHandleRepresentation { @Mock - private ContentCollector representationCollector; - - @BeforeEach - void setUp() { - setRepresentationCollector(representationCollector); - } + private ContentCollector contentCollector; @Nested class TestWithFile { @@ -316,6 +327,14 @@ class EingangStubReceiverStreamObserverTest { @BeforeEach void mock() { when(incomingFileMapper.fromGrpcRepresentationFile(any())).thenReturn(incomingFile); + doNothing().when(observer).verifyNoOngoingFileDownload(); + } + + @Test + void shouldCallVerifyNoOngoingFileDownload() { + observer.handleRepresentation(representationWithFile); + + verify(observer).verifyNoOngoingFileDownload(); } @Test @@ -326,12 +345,12 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldSetRepresentationCollector() { + void shouldSetContentCollector() { var expectedContentCollector = ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build(); observer.handleRepresentation(representationWithFile); - assertThat(getRepresentationCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") + assertThat(getContentCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") .isEqualTo(expectedContentCollector); } @@ -339,7 +358,7 @@ class EingangStubReceiverStreamObserverTest { void shouldNotCollectContent() { observer.handleRepresentation(representationWithFile); - verify(representationCollector, never()).collect(any()); + verify(contentCollector, never()).collect(any()); } } @@ -349,11 +368,23 @@ class EingangStubReceiverStreamObserverTest { private final GrpcRepresentation representationWithContent = GrpcRepresentationTestFactory.createWithContent(); private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + @BeforeEach + void setUp() { + setContentCollector(contentCollector); + } + + @Test + void shouldCallVerifyMetadataWasSent() { + observer.handleRepresentation(representationWithContent); + + verify(observer).verifyMetadataWasSent(); + } + @Test void shouldCollectContent() { observer.handleRepresentation(representationWithContent); - verify(representationCollector).collect(GrpcRepresentationTestFactory.CONTENT); + verify(contentCollector).collect(GrpcRepresentationTestFactory.CONTENT); } @Test @@ -365,7 +396,7 @@ class EingangStubReceiverStreamObserverTest { @Test void shouldCallAddAsRepresentation() { - when(representationCollector.collect(any())).thenReturn(Optional.of(incomingFile)); + when(contentCollector.collect(any())).thenReturn(Optional.of(incomingFile)); observer.handleRepresentation(representationWithContent); @@ -374,7 +405,7 @@ class EingangStubReceiverStreamObserverTest { @Test void shouldNotCallAddAsRepresentation() { - when(representationCollector.collect(any())).thenReturn(Optional.empty()); + when(contentCollector.collect(any())).thenReturn(Optional.empty()); observer.handleRepresentation(representationWithContent); @@ -383,17 +414,49 @@ class EingangStubReceiverStreamObserverTest { } } + @Nested + class TestVerifyNoOngoingFileDownload { + + @Test + void shouldThrowIllegalStateExceptionIfContentCollectorIsNotNull() { + setContentCollector(mock(ContentCollector.class)); + + assertThrows(IllegalStateException.class, () -> observer.verifyNoOngoingFileDownload()); + } + + @Test + void shouldNotThrowExceptionIfContentCollectorIsNull() { + assertDoesNotThrow(() -> observer.verifyNoOngoingFileDownload()); + } + } + + @Nested + class TestVerifyMetadataWasSent { + + @Test + void shouldThrowIllegalStateExceptionIfContentCollectorIsNull() { + assertThrows(IllegalStateException.class, () -> observer.verifyMetadataWasSent()); + } + + @Test + void shouldNotThrowExceptionIfContentCollectorIsNotNull() { + setContentCollector(mock(ContentCollector.class)); + + assertDoesNotThrow(() -> observer.verifyMetadataWasSent()); + } + } + @Nested class TestAddAsAttachment { @Mock - private ContentCollector attachmentCollector; + private ContentCollector contentCollector; private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @BeforeEach void setUp() { - setRepresentationCollector(attachmentCollector); + setContentCollector(contentCollector); setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); } @@ -406,10 +469,10 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldSetAttachmentCollectorToNull() { + void shouldSetContentCollectorToNull() { observer.addAsAttachment(incomingFile); - assertThat(getAttachmentCollector()).isNull(); + assertThat(getContentCollector()).isNull(); } } @@ -417,13 +480,13 @@ class EingangStubReceiverStreamObserverTest { class TestAddAsRepresentation { @Mock - private ContentCollector representationCollector; + private ContentCollector contentCollector; private final IncomingFile incomingFile = IncomingFileTestFactory.create(); @BeforeEach void setUp() { - setRepresentationCollector(representationCollector); + setContentCollector(contentCollector); } @Test @@ -434,10 +497,10 @@ class EingangStubReceiverStreamObserverTest { } @Test - void shouldSetRepresentationCollectorToNull() { + void shouldSetContentCollectorToNull() { observer.addAsRepresentation(incomingFile); - assertThat(getRepresentationCollector()).isNull(); + assertThat(getContentCollector()).isNull(); } } @@ -445,28 +508,19 @@ class EingangStubReceiverStreamObserverTest { class TestOnError { @Mock - private ContentCollector attachmentCollector; - @Mock - private ContentCollector representationCollector; + private ContentCollector contentCollector; @BeforeEach void mock() { - setAttachmentCollector(attachmentCollector); - setRepresentationCollector(representationCollector); + setContentCollector(contentCollector); + setContentCollector(contentCollector); } @Test - void shouldCloseAttachmentCollector() { + void shouldCloseContentCollector() { observer.onError(new Exception()); - verify(attachmentCollector).close(); - } - - @Test - void shouldCloseRepresentationCollector() { - observer.onError(new Exception()); - - verify(representationCollector).close(); + verify(contentCollector).close(); } } @@ -591,20 +645,12 @@ class EingangStubReceiverStreamObserverTest { ReflectionTestUtils.setField(observer, "attachments", attachments); } - private ContentCollector getAttachmentCollector() { - return (ContentCollector) ReflectionTestUtils.getField(observer, "attachmentCollector"); - } - - private void setAttachmentCollector(ContentCollector attachmentCollector) { - ReflectionTestUtils.setField(observer, "attachmentCollector", attachmentCollector); - } - - private ContentCollector getRepresentationCollector() { - return (ContentCollector) ReflectionTestUtils.getField(observer, "representationCollector"); + private ContentCollector getContentCollector() { + return (ContentCollector) ReflectionTestUtils.getField(observer, "contentCollector"); } - private void setRepresentationCollector(ContentCollector representationCollector) { - ReflectionTestUtils.setField(observer, "representationCollector", representationCollector); + private void setContentCollector(ContentCollector contentCollector) { + ReflectionTestUtils.setField(observer, "contentCollector", contentCollector); } } -- GitLab From ea283fb0f27254f85d35624d273ce7dfbce7c7c8 Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Fri, 21 Mar 2025 12:32:05 +0100 Subject: [PATCH 27/28] OZG-7573 add ingress for vorgang-manager --- src/main/helm/templates/network_policy.yaml | 22 ++++++++---- src/test/helm/network_policy_test.yaml | 39 +++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml index 17f7bc782..b4bd33ed1 100644 --- a/src/main/helm/templates/network_policy.yaml +++ b/src/main/helm/templates/network_policy.yaml @@ -22,12 +22,12 @@ # unter der Lizenz sind dem Lizenztext zu entnehmen. # -{{- if not (.Values.networkPolicy).disabled }} +{{- if not (.Values.networkPolicy).disabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: network-policy-{{ .Release.Name}} - namespace: {{ .Release.Namespace }} + namespace: {{ .Release.Namespace }} spec: podSelector: matchLabels: @@ -45,9 +45,19 @@ spec: ports: - protocol: TCP port: 8081 + {{- if (.Values.forwarding).enabled }} + - ports: + - port: 9090 + protocol: TCP + from: + - namespaceSelector: {} + podSelector: + matchLabels: + component: vorgang-manager + {{- end }} egress: - to: - - podSelector: + - podSelector: matchLabels: component: vorgang-manager ports: @@ -72,7 +82,7 @@ spec: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: {{ required "routing.zufiManager.namespace must be set if routingStrategy=ZUFI" ((.Values.routing).zufiManager).namespace }} - podSelector: + podSelector: matchLabels: component: zufi-server ports: @@ -80,7 +90,7 @@ spec: protocol: TCP - to: - namespaceSelector: {} - podSelector: + podSelector: matchLabels: component: vorgang-manager ports: @@ -88,4 +98,4 @@ spec: protocol: TCP {{- end }} -{{- end }} \ No newline at end of file +{{- end }} \ No newline at end of file diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml index d10537996..be4c627e5 100644 --- a/src/test/helm/network_policy_test.yaml +++ b/src/test/helm/network_policy_test.yaml @@ -222,3 +222,42 @@ tests: ports: - port: 9090 protocol: TCP + + - it: should add ingress from vorgang-manager if forwarding is enabled + set: + networkPolicy: + dnsServerNamespace: test-dns-server-namespace + forwarding: + enabled: true + asserts: + - contains: + path: spec.ingress + content: + from: + - namespaceSelector: {} + podSelector: + matchLabels: + component: vorgang-manager + ports: + - port: 9090 + protocol: TCP + + - it: should not add ingress from vorgang-manager if forwarding is disabled + set: + networkPolicy: + dnsServerNamespace: test-dns-server-namespace + forwarding: + enabled: false + asserts: + - notContains: + path: spec.ingress + content: + from: + - namespaceSelector: {} + podSelector: + matchLabels: + component: vorgang-manager + ports: + - port: 9090 + protocol: TCP + any: true -- GitLab From 0be6ccf29fb527407ed84948a64dda762c44cf7c Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Fri, 21 Mar 2025 12:36:35 +0100 Subject: [PATCH 28/28] OZG-7573 add forwarder to fs-adapter --- formcycle-adapter/pom.xml | 4 ++++ pom.xml | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/formcycle-adapter/pom.xml b/formcycle-adapter/pom.xml index 2e7f85ed2..04849487d 100644 --- a/formcycle-adapter/pom.xml +++ b/formcycle-adapter/pom.xml @@ -63,6 +63,10 @@ <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-interface</artifactId> </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>forwarder</artifactId> + </dependency> <dependency> <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-interface</artifactId> diff --git a/pom.xml b/pom.xml index 82d197342..4d92bb83e 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,11 @@ <artifactId>router</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>forwarder</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>de.ozgcloud.eingang</groupId> <artifactId>semantik-adapter</artifactId> -- GitLab