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 4418a4fc7c3c59a0ee27516a4ad6f536a77bf22a..acb3f7384ec445591ad3da3f63f43aef9d6659f1 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 1c5ceaddf1b27323ff33316cb7328533eb904a96..2dc3a7f665e7adc01738d8c7e7ff07ef4b919f3a 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,9 @@ 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"; @@ -54,12 +58,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 +77,15 @@ public class FormDataTestFactory { public static FormData.FormDataBuilder createBuilder() { return FormData.builder() - .header(FormHeaderTestFactory.create()) - .antragsteller(AntragstellerTestFactory.create()) + .id(ID) + .header(HEADER) + .antragsteller(ANTRAGSTELLER) .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/IncomingFileGroupTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileGroupTestFactory.java index ebabd58ef35199c82391f7f4a07c19b35239dcfe..62d245773b2dbefda8ca421920a153fac9f2d2fb 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 03fd991276406c2bb0ef46a4ba54d22704d1c065..85a10843692f48f8707d24649087c9a8cad98009 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; @@ -35,12 +36,13 @@ 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; 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/common/src/test/java/de/ozgcloud/eingang/common/formdata/PostfachAddressTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/PostfachAddressTestFactory.java index 0e3e2a2816168331b48355740403339c9ffe72ec..a7d2fa3ceaa6c4dc68888be3ec6f5450135b22e4 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 5b14fe2d568bb8af1acdd96dbbf2972fac3aa101..34adca8f00a4b850f5b0907ded56566c58d34056 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/eingang-manager-interface/pom.xml b/eingang-manager-interface/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..b877903e6c7055ba30c1a7009f970a992694fe60 --- /dev/null +++ b/eingang-manager-interface/pom.xml @@ -0,0 +1,189 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<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> + <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> + + <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> + <!-- 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> + <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> + <includeMavenTypes>direct</includeMavenTypes> + <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/forward.model.proto b/eingang-manager-interface/src/main/protobuf/forward.model.proto new file mode 100644 index 0000000000000000000000000000000000000000..29076e289280f43cb1693eefe6b74696404dea74 --- /dev/null +++ b/eingang-manager-interface/src/main/protobuf/forward.model.proto @@ -0,0 +1,94 @@ +/* + * 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. + */ +syntax = "proto3"; + +package de.ozgcloud.eingang.forwarder; + +import "vorgang.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 { + de.ozgcloud.vorgang.vorgang.GrpcEingangHeader header = 1; + de.ozgcloud.vorgang.vorgang.GrpcAntragsteller antragsteller = 2; + de.ozgcloud.vorgang.vorgang.GrpcFormData formData = 3; +} + +message GrpcRouteCriteria { + string organisationEinheitId = 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/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java b/eingang-manager-interface/src/main/protobuf/forward.proto similarity index 70% rename from forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java rename to eingang-manager-interface/src/main/protobuf/forward.proto index b52e416dd52104bc590d4e2f309fdc44660a93bb..ef695a3e83718e9316070406ea00d37e566a42f8 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteria.java +++ 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 @@ -21,18 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +syntax = "proto3"; + package de.ozgcloud.eingang.forwarder; -import java.util.Optional; +import "forward.model.proto"; + +option java_multiple_files = true; +option java_package = "de.ozgcloud.eingang.forwarder"; +option java_outer_classname = "RouteForwardingProto"; -import lombok.Builder; -import lombok.Getter; +service RouteForwardingService { -@Getter -@Builder -public class RouteCriteria { + rpc RouteForwarding(stream GrpcRouteForwardingRequest) returns (GrpcRouteForwardingResponse) { + } - private Optional<String> gemeindeSchluessel; - private Optional<String> webserviceUrl; - private Optional<String> organisationseinheitenId; -} +} \ No newline at end of file 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 0c65466d79e1fdb5f0f5e5472fbd2bed4b013536..e7b648eee846205964c148f365b83d6b58fe25fd 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 6d527356735d785b8f113da8d22473e8d200611c..b3dea53e5c1e0628909b7d852db8d3b8691b3c55 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 de7e3961ccb4ae9b99eedf79c8c25beccc4d4abb..8301f01eaf84d0c1cf3280cf81d3f9e83d7c46ba 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 054589340915925e6aa49ca9da20c88858eb377b..9fefeba4d8e90153bb214b2ffe78a292d00b77d1 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 63befb6637b368805c57cfe354df8d4974ad74ba..632636410382b8c6f230d6ef962d1e8efd7894a6 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 68be9eb443298ed45cafcbe646f73b85de9c6519..c7333daf4d31c4fac797a0532f27ef551f3bafa4 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 2368cd4ddd96ed23fe11e3c8553391d78fd19e22..966b2cc08c3ca86bde05d2c797990b4fccbc48f3 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 f6daa78ea5d7a00b56f86ed99941c87e1e0d6cc7..8dd4950ece666f960e734af705df74aa2efd48b5 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 e72806960894dce1f415e28f1624369c96852c71..6e14ba107049d8ecb2743524c05db215079c40a1 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 e32906bc408d40d53b0fc8969f6aa0fa5fd63bf3..ac669d63c5ae513bee4f8aadd44e7fdddcd8dd9c 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 cb48785bcad73409f81fb3606a8f4e260b745445..631029fe3284289e82752e62d7c3ffe537856674 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 610263cc895893fd2abe162e469b405df679b7da..e5bbe51daf0c4f9b39f91fe35ee117496b1c50fd 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 7553fefb39eecae195f94a9fa79706efad3d5d52..d768484446fa499efa389c4caf58ea40043a9a66 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 4d090842c766264a4886e3251acf72358d0d6152..c9ff9d8de6153bae94ca16bfbcc59f2d5ab74d4e 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 eef87830a7eaa9b3760d037b07cb9d24dc692315..b552254518b9c70f218f34a227595cfa42e895b8 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/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 066b77ac5bcafacce46dab4070ea6f9bc52a7630..edff3cd6ccbf0a7863bfaca5fa8dbea645ea59c6 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 f63d7df6efbe2c562f896b60e7d1981fdd32e726..61daa9f4a91a7690dd119bd7c2819553d8f00435 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 af16a675df3161341c8fcec51aec4f96a16f4607..e9fdd387fcc97a176170c63cf40e392e7fa1b3f4 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/formcycle-adapter/pom.xml b/formcycle-adapter/pom.xml index 2e7f85ed29e3331585bbcf5adaa8ab7b0972b3d0..04849487dd004df43e50d441f61f2ef539c63b52 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/forwarder/pom.xml b/forwarder/pom.xml index 8e11aac68cb31e2265202b09a8cef1a841d69293..4fabecd6af1c23ce9d991e6c1db97a49c706da87 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> @@ -86,6 +90,25 @@ <artifactId>lombok</artifactId> </dependency> + <!-- Test --> + <dependency> + <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> <build> 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 0000000000000000000000000000000000000000..5099f2385c580c3651e302d509ed9e43cb5defd8 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..40dbc1b1a0adec125848dd949d3da0f1ca3eaf33 --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserver.java @@ -0,0 +1,171 @@ +/* + * 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.InputStream; +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.function.Consumer; +import java.util.function.Function; + +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.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; + +@Log4j2 +class EingangStubReceiverStreamObserver implements StreamObserver<GrpcRouteForwardingRequest> { + + private final RouteForwardingMapper routeForwardingMapper; + private final IncomingFileMapper incomingFileMapper; + 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<GrpcRouteForwardingResponse> responseConsumer) { + this.routeForwardingMapper = routeForwardingMapper; + this.incomingFileMapper = incomingFileMapper; + this.incomingFileGroupMapper = incomingFileGroupMapper; + this.fileSaver = fileSaver; + this.formDataConsumer = formDataConsumer; + this.responseConsumer = responseConsumer; + } + + private FormData formData; + private final List<IncomingFile> representations = new ArrayList<>(); + private final Map<String, List<IncomingFile>> attachments = new HashMap<>(); + + private String groupName; + private ContentCollector contentCollector; + + @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()); + } + } + + void handleRouteForwarding(GrpcRouteForwarding routeForwarding) { + if (Objects.nonNull(formData)) { + throw new IllegalStateException("Received second RouteForwarding. Send only one per request."); + } + formData = routeForwardingMapper.toFormData(routeForwarding); + } + + void handleAttachment(GrpcAttachment attachment) { + if (attachment.hasFile()) { + verifyNoOngoingFileDownload(); + contentCollector = buildContentCollector(incomingFileMapper.fromGrpcAttachmentFile(attachment.getFile())); + groupName = attachment.getFile().getGroupName(); + } else { + verifyMetadataWasSent(); + contentCollector.collect(attachment.getContent()).ifPresent(this::addAsAttachment); + } + } + + void handleRepresentation(GrpcRepresentation representation) { + if (representation.hasFile()) { + verifyNoOngoingFileDownload(); + contentCollector = buildContentCollector(incomingFileMapper.fromGrpcRepresentationFile(representation.getFile())); + } else { + 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."); + } + } + + private ContentCollector buildContentCollector(IncomingFile incomingFile) { + return ContentCollector.builder() + .fileSaver(fileSaver) + .incomingFile(incomingFile) + .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); + contentCollector = null; + } + + void addAsRepresentation(IncomingFile completedIncomingFile) { + representations.add(completedIncomingFile); + contentCollector = null; + } + + @Override + public synchronized void onError(Throwable t) { + LOG.error("Error happened. Receiving stream closed.", t); + contentCollector.close(); + } + + @Override + public synchronized void onCompleted() { + formDataConsumer.accept(assembleFormData()); + responseConsumer.accept(GrpcRouteForwardingResponse.getDefaultInstance()); + } + + 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/main/java/de/ozgcloud/eingang/forwarder/FileService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java new file mode 100644 index 0000000000000000000000000000000000000000..91dcc0d3ea23794565de280ac8bfd192dd2401db --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/FileService.java @@ -0,0 +1,43 @@ +/* + * 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.InputStream; +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) { + return CompletableFuture.completedFuture(TempFileUtils.writeTmpFile(inputStream)); + } + +} diff --git a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java similarity index 67% rename from forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java rename to forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.java index d82fbd76b46f70c91d4fb175a0c69d42e2b2fb9d..ba1939b216c851f0af1f1b74f47248f351fcad7b 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteCriteriaMapper.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapper.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 @@ -23,19 +23,21 @@ */ package de.ozgcloud.eingang.forwarder; -import java.util.Optional; +import java.util.List; +import java.util.Map; -import org.apache.commons.lang3.StringUtils; import org.mapstruct.Mapper; -import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; @Mapper -interface RouteCriteriaMapper { +public interface IncomingFileGroupMapper { - RouteCriteria fromGrpc(GrpcRouteCriteria grpcRouteCriteria); - - default Optional<String> wrapWithOptional(String val) { - return Optional.ofNullable(StringUtils.trimToNull(val)); + default IncomingFileGroup fromMapEntry(Map.Entry<String, List<IncomingFile>> entry) { + return IncomingFileGroup.builder() + .name(entry.getKey()) + .files(entry.getValue()) + .build(); } } 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 0000000000000000000000000000000000000000..40176db7151e5c00e974300dbcb1b36bff0a74da --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/IncomingFileMapper.java @@ -0,0 +1,45 @@ +/* + * 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; +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/RouteForwardingGrpcService.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java index fa9c9d99a6ccb8c303eba891c60770b89daf35ce..322e7361ff4f3cc58808e60e14cd3103eab90804 100644 --- a/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcService.java @@ -23,27 +23,45 @@ */ package de.ozgcloud.eingang.forwarder; -import org.springframework.beans.factory.annotation.Autowired; +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; @GrpcService +@RequiredArgsConstructor public class RouteForwardingGrpcService extends RouteForwardingServiceGrpc.RouteForwardingServiceImplBase { - @Autowired - private RouteForwardingService service; - @Autowired - private RouteCriteriaMapper criteriaMapper; - - @Autowired - private GrpcEingangMapper eingangMapper; + private final RouteForwardingMapper routeForwardingMapper; + private final IncomingFileMapper incomingFileMapper; + private final IncomingFileGroupMapper incomingFileGroupMapper; + private final RouteForwardingService routeForwardingService; + private final FileService fileService; @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) { + 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/RouteForwardingMapper.java b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3665e7f6c4ec8e65f721796aefcd2022101c148c --- /dev/null +++ b/forwarder/src/main/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapper.java @@ -0,0 +1,66 @@ +/* + * 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.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; + +import de.ozgcloud.eingang.common.formdata.Antragsteller; +import de.ozgcloud.eingang.common.formdata.FormData; +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(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // + 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) + @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 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 0079be1be32bbe6c4d23ba12f491acb126840c9f..40e9b7707c89c642ec0a56b6f45aca9299aa6d3a 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,16 @@ package de.ozgcloud.eingang.forwarder; import org.springframework.stereotype.Service; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.router.VorgangService; +import lombok.RequiredArgsConstructor; @Service +@RequiredArgsConstructor class RouteForwardingService { - public void route(RouteCriteria criteria, FormData formData) { -//FIXME implement me + private final VorgangService vorgangService; + + public void route(FormData formData) { + vorgangService.createVorgang(formData); } } 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 0000000000000000000000000000000000000000..4385eb7ef202481c49941943c58288129ec9804c --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..c8e6dce6b1fbdc17bced5a05bc48dd74b981a501 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/EingangStubReceiverStreamObserverTest.java @@ -0,0 +1,656 @@ +/* + * 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.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +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.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.GrpcRepresentation; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding; +import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse; + +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 { + + @Mock + private ContentCollector contentCollector; + + @Nested + class TestWithFile { + + private final GrpcAttachment attachmentWithFile = GrpcAttachmentTestFactory.createWithFile(); + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void initMock() { + when(incomingFileMapper.fromGrpcAttachmentFile(any())).thenReturn(incomingFile); + doNothing().when(observer).verifyNoOngoingFileDownload(); + } + + @Test + void shouldCallVerifyNoOngoingFileDownload() { + observer.handleAttachment(attachmentWithFile); + + verify(observer).verifyNoOngoingFileDownload(); + } + + @Test + void shouldCallIncomingFileMapper() { + observer.handleAttachment(attachmentWithFile); + + verify(incomingFileMapper).fromGrpcAttachmentFile(GrpcAttachmentTestFactory.FILE); + } + + @Test + void shouldSetContentCollector() { + var expectedContentCollector = ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build(); + + observer.handleAttachment(attachmentWithFile); + + assertThat(getContentCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") + .isEqualTo(expectedContentCollector); + } + + @Test + void shouldSetGroupName() { + observer.handleAttachment(attachmentWithFile); + + assertThat(getGroupName()).isEqualTo(GrpcAttachmentFileTestFactory.GROUP_NAME); + } + + @Test + void shouldNotCollectContent() { + observer.handleAttachment(attachmentWithFile); + + verify(contentCollector, never()).collect(any()); + } + } + + @Nested + class TestWithContent { + + 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(contentCollector).collect(GrpcAttachmentTestFactory.CONTENT); + } + + @Test + void shouldNotCallIncomingFileMapper() { + observer.handleAttachment(attachmentWithContent); + + verify(incomingFileMapper, never()).fromGrpcAttachmentFile(any()); + } + + @Test + void shouldNotSetGroupName() { + observer.handleAttachment(attachmentWithContent); + + assertThat(getGroupName()).isNull(); + } + + @Test + void shouldCallAddAsAttachment() { + when(contentCollector.collect(any())).thenReturn(Optional.of(incomingFile)); + + observer.handleAttachment(attachmentWithContent); + + verify(observer).addAsAttachment(incomingFile); + } + + @Test + void shouldNotCallAddAsAttachment() { + when(contentCollector.collect(any())).thenReturn(Optional.empty()); + + observer.handleAttachment(attachmentWithContent); + + verify(observer, never()).addAsAttachment(any()); + } + + } + } + + @Nested + class TestHandleRepresentation { + + @Mock + private ContentCollector contentCollector; + + @Nested + class TestWithFile { + + private final GrpcRepresentation representationWithFile = GrpcRepresentationTestFactory.createWithFile(); + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void mock() { + when(incomingFileMapper.fromGrpcRepresentationFile(any())).thenReturn(incomingFile); + doNothing().when(observer).verifyNoOngoingFileDownload(); + } + + @Test + void shouldCallVerifyNoOngoingFileDownload() { + observer.handleRepresentation(representationWithFile); + + verify(observer).verifyNoOngoingFileDownload(); + } + + @Test + void shouldCallIncomingFileMapper() { + observer.handleRepresentation(representationWithFile); + + verify(incomingFileMapper).fromGrpcRepresentationFile(GrpcRepresentationTestFactory.FILE); + } + + @Test + void shouldSetContentCollector() { + var expectedContentCollector = ContentCollector.builder().fileSaver(fileSaver).incomingFile(incomingFile).build(); + + observer.handleRepresentation(representationWithFile); + + assertThat(getContentCollector()).usingRecursiveComparison().ignoringFields("pipedInput", "pipedOutput") + .isEqualTo(expectedContentCollector); + } + + @Test + void shouldNotCollectContent() { + observer.handleRepresentation(representationWithFile); + + verify(contentCollector, never()).collect(any()); + } + } + + @Nested + class TestWithContent { + + 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(contentCollector).collect(GrpcRepresentationTestFactory.CONTENT); + } + + @Test + void shouldNotCallIncomingFileMapper() { + observer.handleRepresentation(representationWithContent); + + verify(incomingFileMapper, never()).fromGrpcRepresentationFile(any()); + } + + @Test + void shouldCallAddAsRepresentation() { + when(contentCollector.collect(any())).thenReturn(Optional.of(incomingFile)); + + observer.handleRepresentation(representationWithContent); + + verify(observer).addAsRepresentation(incomingFile); + } + + @Test + void shouldNotCallAddAsRepresentation() { + when(contentCollector.collect(any())).thenReturn(Optional.empty()); + + observer.handleRepresentation(representationWithContent); + + verify(observer, never()).addAsRepresentation(any()); + } + } + } + + @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 contentCollector; + + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void setUp() { + setContentCollector(contentCollector); + setGroupName(GrpcAttachmentFileTestFactory.GROUP_NAME); + } + + @Test + void shouldAddFileToAttachments() { + observer.addAsAttachment(incomingFile); + + var attachmentGroup = getAttachments().get(GrpcAttachmentFileTestFactory.GROUP_NAME); + assertThat(attachmentGroup).usingRecursiveFieldByFieldElementComparator().containsExactly(incomingFile); + } + + @Test + void shouldSetContentCollectorToNull() { + observer.addAsAttachment(incomingFile); + + assertThat(getContentCollector()).isNull(); + } + } + + @Nested + class TestAddAsRepresentation { + + @Mock + private ContentCollector contentCollector; + + private final IncomingFile incomingFile = IncomingFileTestFactory.create(); + + @BeforeEach + void setUp() { + setContentCollector(contentCollector); + } + + @Test + void shouldAddFileToRepresentations() { + observer.addAsRepresentation(incomingFile); + + assertThat(getRepresentations()).usingRecursiveFieldByFieldElementComparator().containsExactly(incomingFile); + } + + @Test + void shouldSetContentCollectorToNull() { + observer.addAsRepresentation(incomingFile); + + assertThat(getContentCollector()).isNull(); + } + } + + @Nested + class TestOnError { + + @Mock + private ContentCollector contentCollector; + + @BeforeEach + void mock() { + setContentCollector(contentCollector); + setContentCollector(contentCollector); + } + + @Test + void shouldCloseContentCollector() { + observer.onError(new Exception()); + + verify(contentCollector).close(); + } + } + + @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); + } + + private String getGroupName() { + return (String) ReflectionTestUtils.getField(observer, "groupName"); + } + + private void setGroupName(String groupName) { + ReflectionTestUtils.setField(observer, "groupName", groupName); + } + + @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); + } + + private ContentCollector getContentCollector() { + return (ContentCollector) ReflectionTestUtils.getField(observer, "contentCollector"); + } + + private void setContentCollector(ContentCollector contentCollector) { + ReflectionTestUtils.setField(observer, "contentCollector", contentCollector); + } + +} 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 0000000000000000000000000000000000000000..dbf23b168f5d88dd004762a2bafc799799ed161c --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/FileServiceTest.java @@ -0,0 +1,62 @@ +/* + * 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 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); + + } + } + + } +} diff --git a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAntragstellerTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAntragstellerTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..c125f88655416d9d9e9da4ed195be2e034a5c2cc --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/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.forwarder; + +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/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 0000000000000000000000000000000000000000..ec48f44e48beb0c2d0cd072050bd7494a1effac3 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentFileTestFactory.java @@ -0,0 +1,48 @@ +/* + * 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.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 = IncomingFileGroupTestFactory.NAME; + + 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/GrpcAttachmentTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcAttachmentTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e5593e13f415f71ceee9fd21e5fb548383f7d8eb --- /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/GrpcEingangStubTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..f1fc1c66423606d998d54ee9a620cb736bc2a3aa --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcEingangStubTestFactory.java @@ -0,0 +1,50 @@ +/* + * 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.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/GrpcFileContentTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcFileContentTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d4040f97517ce4c6a379d38eaeb173bc96bf90d0 --- /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/GrpcRepresentationFileTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e5155199a28dc9e762cce685495fadc220eb5eec --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationFileTestFactory.java @@ -0,0 +1,44 @@ +/* + * 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; +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/GrpcRepresentationTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRepresentationTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e437c900d0a49cf0f714d4d7718a9f699d681af8 --- /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/RouteCriteriaTestFactory.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java similarity index 53% rename from forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java rename to forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.java index f5b8c2742f66a3ac5119e5f1965e8751f3655c9b..450f68612ac6d32959aba874a3b7e0a5fa31932f 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteCriteriaTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteCriteriaTestFactory.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 @@ -23,35 +23,22 @@ */ package de.ozgcloud.eingang.forwarder; -import java.util.Optional; +import java.util.UUID; import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria; +import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria.Builder; -public class RouteCriteriaTestFactory { +public class GrpcRouteCriteriaTestFactory { - 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 = UUID.randomUUID().toString(); - public static RouteCriteria create() { + public static GrpcRouteCriteria create() { return createBuilder().build(); } - public static RouteCriteria.RouteCriteriaBuilder createBuilder() { - return RouteCriteria.builder() - .gemeindeSchluessel(Optional.of(GEMEINDE_SCHLUSSEL)) - .webserviceUrl(Optional.of(WEBSERVICE_URL)) - .organisationseinheitenId(Optional.of(ORGANISATIONSEINHEITEN_ID)); - } - - public static GrpcRouteCriteria createGrpc() { - return createGrpcBuilder().build(); - } - - public static GrpcRouteCriteria.Builder createGrpcBuilder() { + public static Builder createBuilder() { return GrpcRouteCriteria.newBuilder() - .setGemeindeSchluessel(GEMEINDE_SCHLUSSEL) - .setWebserviceUrl(WEBSERVICE_URL) - .setOrganisationseinheitenId(ORGANISATIONSEINHEITEN_ID); + .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 03c5beaeddc4b13c6dd1f8ad51459f63097bd951..a05ac9a84aa68f8deae2657d2e4e64fd37879291 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingRequestTestFactory.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 @@ -23,16 +23,32 @@ */ 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 GrpcRouteForwardingRequest create() { - return createBuilder().build(); + 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.Builder createBuilder() { + public static GrpcRouteForwardingRequest createWithRepresentation() { return GrpcRouteForwardingRequest.newBuilder() - .setRouteCriteria(RouteCriteriaTestFactory.createGrpc()); + .setRepresentation(REPRESENTATION) + .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 0000000000000000000000000000000000000000..ca29d219b92c0c9a0c1f7838bae3286059d8dd23 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/GrpcRouteForwardingTestFactory.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.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/IncomingFileGroupMapperTest.java b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b86144b64161e91f58368ca6f3ff92c93d0a0e1f --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileGroupMapperTest.java @@ -0,0 +1,52 @@ +/* + * 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 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()); + } + } +} 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 0000000000000000000000000000000000000000..c8b12b9f1cb7ef9adc9b6e37b616ad3dbe59bce2 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/IncomingFileMapperTest.java @@ -0,0 +1,63 @@ +/* + * 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 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()); + } + } +} 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 e4dd78ddb466c0538814676dd3f8587fa550782c..35ac8140ce6cc4b7acd21cca3f6a0e15b06649dc 100644 --- a/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingGrpcServiceTest.java @@ -27,63 +27,182 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +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.mapstruct.factory.Mappers; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; 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; - @Spy - private RouteCriteriaMapper criteriaMapper = Mappers.getMapper(RouteCriteriaMapper.class); - @Spy - private GrpcEingangMapper eingangMapper = Mappers.getMapper(GrpcEingangMapper.class); + private RouteForwardingMapper routeForwardingMapper; + @Mock + private IncomingFileMapper incomingFileMapper; + @Mock + private IncomingFileGroupMapper incomingFileGroupMapper; + @Mock + 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); - @Captor - private ArgumentCaptor<RouteCriteria> criteriaCaptor; + private final FormData formData = FormDataTestFactory.create(); @Test - void shouldCallService() { - service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); + void shouldSetFileSaver() { + var observer = service.routeForwarding(responseObserver); - verify(routeService).route(any(), any()); + callFileSaver(observer); + verify(service).saveFile(INPUT_STREAM); } @Test - void shouldHaveRouteCriteria() { - service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); + 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; + } - verify(routeService).route(criteriaCaptor.capture(), any()); + private IncomingFileGroupMapper getIncomingFileGroupMapper(StreamObserver<GrpcRouteForwardingRequest> uploadObserver) { + var incomingFileGroupMapper = (IncomingFileGroupMapper) ReflectionTestUtils.getField(uploadObserver, "incomingFileGroupMapper"); + return incomingFileGroupMapper; + } - assertThat(criteriaCaptor.getValue()).usingRecursiveComparison().isEqualTo(RouteCriteriaTestFactory.create()); + @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 { + + @Mock + private InputStream inputStream; + @Mock + private CompletableFuture<File> fileFuture; + @Test - void shouldHaveFormData() { - service.routeForwarding(GrpcRouteForwardingRequestTestFactory.create(), responseObserver); + void shouldReturnNull() { + service.saveFile(inputStream); - verify(routeService).route(any(), notNull()); - verify(eingangMapper).toFormData(any()); + verify(fileService).saveToFile(inputStream); + } + + @Test + void shouldReturnFileFuture() { + when(fileService.saveToFile(any())).thenReturn(fileFuture); + + var result = service.saveFile(inputStream); + + 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(); + } + } } 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 0000000000000000000000000000000000000000..406c6e1bd700ebde38acdbb237a49d4996685f3b --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingMapperTest.java @@ -0,0 +1,123 @@ +/* + * 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.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.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 new file mode 100644 index 0000000000000000000000000000000000000000..4b36715c71b92587c4522f669a8631a4d527b6c7 --- /dev/null +++ b/forwarder/src/test/java/de/ozgcloud/eingang/forwarder/RouteForwardingServiceTest.java @@ -0,0 +1,56 @@ +/* + * 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.mockito.Mockito.*; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +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.router.VorgangService; + +class RouteForwardingServiceTest { + + @InjectMocks + private RouteForwardingService routeForwardingService; + @Mock + private VorgangService vorgangService; + + @Nested + class TestRoute { + + private final FormData formData = FormDataTestFactory.create(); + + @Test + void shouldCallVorgangService() { + routeForwardingService.route(formData); + + verify(vorgangService).createVorgang(formData); + } + } +} diff --git a/pom.xml b/pom.xml index ce7c182f5e8169cd94182f41dd29ae3f3f1cfe06..4d92bb83ed28b5166aaaa4757bcd44bd8d5baa46 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,11 +76,21 @@ <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> <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> @@ -126,6 +137,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 7130d2c1e52b111ebd0b1600c9ad76e614fcb97b..f0659ace437ff2c4e26c281df46951dc54e7fb58 100644 --- a/router/pom.xml +++ b/router/pom.xml @@ -96,6 +96,18 @@ <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/main/java/de/ozgcloud/eingang/common/zufi/XzufiId.java b/router/src/main/java/de/ozgcloud/eingang/common/zufi/XzufiId.java index ff731658b7be8e9afbf001627923667b48ec49ab..bbcb44b94655bca0f778332dde1f395cf97587c3 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/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java b/router/src/main/java/de/ozgcloud/eingang/router/GrpcEingangMapper.java index eb5d7c414ef8361bfcc348e1f2544a563ce853a5..b5fd75f9ad35d3c57c5d506518c269011cf48815 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()); } @@ -83,14 +82,4 @@ public interface GrpcEingangMapper { default String uuidToString(UUID id) { 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) - FormData toFormData(GrpcEingang eingang); - } 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 7986140e79963d3d4183146800211926678fb748..97aed9ca47f8d3de4a560c577687186f56b4a7e3 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 }) +public 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) + public 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/GrpcEingangHeaderTestFactory.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangHeaderTestFactory.java index e7fbc2a6de22ef4cd73d3719433326f517ac0e6a..1c2f14b48549cbf74fa2c97f2a1e2a5890dbde26 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/GrpcEingangMapperITCase.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperITCase.java index 55e1b3ef348ce7c2f4a0bb418ef36195d0d56276..758fcd0ef1e924d7161e08eae22ee38325b7da3c 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/GrpcEingangMapperTest.java b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java index 15ee7c6b776beb4fb5a8ff3074b562b44fbf55fd..eed08a8959bfb6067b971d92fa12b88613dad87a 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcEingangMapperTest.java @@ -45,7 +45,6 @@ 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 +108,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 +133,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 +161,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 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 8ffea979664c5c311d1130f87208667986df15e9..e8082ab9164a882cbcd9e7c2546424699925addc 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 dc5899c75627723337f54ec388396f35d9fa9abe..f72d588d6a437fa106b73f166c667bc6c76b75a7 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 0000000000000000000000000000000000000000..902a463e9e880b9460a9109ffc7fb3925b16dbd1 --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcPostfachAddressTestFactory.java @@ -0,0 +1,56 @@ +/* + * 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; +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 0000000000000000000000000000000000000000..d223b64c551bdb7225826ee35e16cc0b3edd5039 --- /dev/null +++ b/router/src/test/java/de/ozgcloud/eingang/router/GrpcServiceKontoTestFactory.java @@ -0,0 +1,48 @@ +/* + * 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; +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/ServiceKontoMapperTest.java b/router/src/test/java/de/ozgcloud/eingang/router/ServiceKontoMapperTest.java index 34cc0776f020dcf4d9d1a578b8b587d2d2b3c42c..f6389906f7b4f1dc95fd744ba75c341faba0d82a 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 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 7fda033b4b16edb312f09bc90f213392b3058a16..cc8cef24be0ae7c43b0a43fa6d80b9bd67e78c71 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 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 d69b36c664c87f2ad0116cf5e8f2e033a1358ec2..bd5ff001ac043671b3760e34a6921ac5c71b844e 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()); } } 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 8576eb31d22093b5599b44b2381cf960eff2956b..594048a728e4da6dab7cc83fad469a2d5844d47a 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; @@ -5,10 +28,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(); diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml index 17f7bc782764722ca058e3261575128f7906d50b..b4bd33ed128b4dd3fc2a5283de4c58018bfaecfa 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 d10537996010737c734c64c2cf2ffaecad92b3e8..be4c627e54167089a6137125149b2dcd964976e5 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