diff --git a/Jenkinsfile b/Jenkinsfile index f28561ef01011852566b67659718aa65eafad4aa..258cfa2497436f696c9e9e7216286f18ca3af206 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -52,6 +52,26 @@ pipeline { } } } + stage('Set Version') { + when { + not { + anyOf { + branch 'master' + branch 'release' + } + } + } + steps { + script { + FAILED_STAGE=env.STAGE_NAME + JAR_TAG = getPomVersion('pom.xml').replace("SNAPSHOT", "${env.BRANCH_NAME}-SNAPSHOT") + } + configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { + sh "mvn -s $MAVEN_SETTINGS versions:set -DnewVersion=${JAR_TAG} -DprocessAllModules=true" + + } + } + } stage('Build Eingang-Adapter') { steps { script { @@ -82,18 +102,13 @@ pipeline { } stage('Deploy Eingang-Adapter to Nexus'){ - when { - anyOf { - branch 'master' - branch 'release' - } - } steps { script { FAILED_STAGE = env.STAGE_NAME } configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { sh 'mvn -s $MAVEN_SETTINGS -DskipTests deploy' + sh "mvn -s $MAVEN_SETTINGS versions:revert" } } } @@ -262,7 +277,7 @@ Void sendFailureMessage() { "formatted_body":"Eingang-Manager: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>"}""" if (env.BRANCH_NAME == 'master') { - room = "!iQPAvQIiRwRpNOszjw:matrix.ozg-sh.de" + room = "!GjqhmouBtnDbwUkAjx:matrix.ozg-sh.de" } else if (env.BRANCH_NAME == 'release') { room = "!oWZpUGTFsxkJIYNfYg:matrix.ozg-sh.de" diff --git a/common/pom.xml b/common/pom.xml index 0d014f643b4e14bc198be9cf3fee612e17f42ee1..70598d2ad26668f38f22ede62c3ab0862d4252c7 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -31,7 +31,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> <artifactId>common</artifactId> diff --git a/enterprise-adapter/pom.xml b/enterprise-adapter/pom.xml index 86cd361960b46a6f76dc40a06e552d3fe0392375..b29a4958efd96f456fe013fb92df117d5219af81 100644 --- a/enterprise-adapter/pom.xml +++ b/enterprise-adapter/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> </parent> <artifactId>enterprise-adapter</artifactId> <name>EM - Enterprise Interface Adapter</name> diff --git a/fim-adapter/pom.xml b/fim-adapter/pom.xml index e3acc94b6541b7e0114f613c3c0d69ab85c77a72..b5c5d81c7055305f5ff5a86f9dc5d86a03c50292 100644 --- a/fim-adapter/pom.xml +++ b/fim-adapter/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> </parent> <artifactId>fim-adapter</artifactId> <name>Eingangs Adapter - FIM</name> diff --git a/formcycle-adapter/formcycle-adapter-impl/pom.xml b/formcycle-adapter/formcycle-adapter-impl/pom.xml index ed03ed830eec84d901e4204ac5744348f38ce11b..d0fcff5c790c8265c8bdc57a73baee375bd9d332 100644 --- a/formcycle-adapter/formcycle-adapter-impl/pom.xml +++ b/formcycle-adapter/formcycle-adapter-impl/pom.xml @@ -29,7 +29,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>formcycle-adapter</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/formcycle-adapter/formcycle-adapter-interface/pom.xml b/formcycle-adapter/formcycle-adapter-interface/pom.xml index 5951e22341367d1318a44e630d0b6baf4035d8f7..7c37029d6b5e88778e5996cb04b87014e3892d9d 100644 --- a/formcycle-adapter/formcycle-adapter-interface/pom.xml +++ b/formcycle-adapter/formcycle-adapter-interface/pom.xml @@ -36,7 +36,7 @@ <groupId>de.ozgcloud.eingang</groupId> <artifactId>formcycle-adapter-interface</artifactId> <name>EM - Formcycle Adapter - Interface</name> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <properties> <vorgang-manager.version>2.0.0</vorgang-manager.version> diff --git a/formcycle-adapter/pom.xml b/formcycle-adapter/pom.xml index 63b93d221b06b16291daed58ab4fe63eaa69d2cc..0936aec04450ceac41ef5d3aa9c103fa42055faf 100644 --- a/formcycle-adapter/pom.xml +++ b/formcycle-adapter/pom.xml @@ -29,7 +29,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> </parent> <artifactId>formcycle-adapter</artifactId> diff --git a/formsolutions-adapter/pom.xml b/formsolutions-adapter/pom.xml index 03eb9a613234b0185ad0dc5baa5845924afa19c6..2cea17c8432640e98cc7bd896d7f81ff8dafdc82 100644 --- a/formsolutions-adapter/pom.xml +++ b/formsolutions-adapter/pom.xml @@ -30,7 +30,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/forwarder/pom.xml b/forwarder/pom.xml index e42078568cc69cd957b06d28469984bf9a4ddec4..8cc7e8e36c9911496b831b12889179e946fef08d 100644 --- a/forwarder/pom.xml +++ b/forwarder/pom.xml @@ -29,7 +29,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/intelliform-adapter/pom.xml b/intelliform-adapter/pom.xml index c5a62fb727d1b2d2c5874064eb54ade65443a994..d73352c2c11f6a23fbdb207515bf8187f06c87a8 100644 --- a/intelliform-adapter/pom.xml +++ b/intelliform-adapter/pom.xml @@ -31,7 +31,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java index b12dfc7a99548a5868891da6608dab10242e64d2..f4b42d22220e907979e96ccdc21b684084ef0ac7 100644 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java +++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java @@ -71,8 +71,8 @@ class DepositDataMapper { } public FormData mapToFormData(DepositData depositData) { - Map<String, IncomingFile> incomingFileMap = mapDepositAttachmentsToIncomingFiles(depositData); - Document document = parsePrimaryXmlRepresentation(depositData, incomingFileMap); + var incomingFileMap = mapDepositAttachmentsToSortedIncomingFiles(depositData); + var document = parsePrimaryXmlRepresentation(depositData, incomingFileMap); var attachmentGroups = findAttachmentGroups(document); return mapToFormDataWithRepresentationsAndAttachments( @@ -99,7 +99,14 @@ class DepositDataMapper { .build(); } - Map<String, IncomingFile> mapDepositAttachmentsToIncomingFiles(DepositData depositData) { + Map<String, IncomingFile> mapDepositAttachmentsToSortedIncomingFiles(DepositData depositData) { + var incomingFilesMap = mapDepositAttachmentsToIncomingFiles(depositData); + var primaryId = depositData.getPrimaryDataAttachmentId(); + incomingFilesMap.putFirst(primaryId, getIncomingFileById(primaryId, incomingFilesMap)); + return incomingFilesMap; + } + + private LinkedHashMap<String, IncomingFile> mapDepositAttachmentsToIncomingFiles(DepositData depositData) { return depositData.getAttachments() .stream() .collect(Collectors.toMap( diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java index 0bc63fd67c648f3a51d7a57942cd5414a3293262..a2157603218be1f371cd3d516e93640ba2bb5703 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java @@ -54,6 +54,8 @@ public class AttachmentTestFactory { </myForm>"""; public static final String XML_CONTENT = XML_CONTENT_STRING; public static final String XML_ATTACHMENT_ID = "myForm-xml"; + public static final String XML_ROHFORM_ATTACHMENT_ID = "myForm-xml-rohform"; + public static final String XML_ORIGINALFORM_ATTACHMENT_ID = "myForm-xml-originalform"; public static final String XML_NAME = "XML-Daten.xml"; public static final String PDF_ATTACHMENT_CONTENT_TYPE = "application/pdf"; @@ -114,7 +116,7 @@ public class AttachmentTestFactory { .build()); } - private static Attachment createAttachment(MetaAttachment metaAttachment) { + public static Attachment createAttachment(MetaAttachment metaAttachment) { var attachment = new Attachment(); attachment.getAttributes().add(createAttributesEntry()); attachment.setContent(metaAttachment.content.getBytes()); @@ -147,7 +149,22 @@ public class AttachmentTestFactory { ); return Stream.concat( - Stream.of(createXmlDatenWithContent(xmlFormString)), + Stream.of( + createAttachment(MetaAttachment.builder() + .id(XML_ROHFORM_ATTACHMENT_ID) + .name("XML-Daten (Rohform).xml") + .contentType(XML_CONTENT_TYPE) + .content(xmlFormString) + .build() + ), + createAttachment(MetaAttachment.builder() + .id(XML_ORIGINALFORM_ATTACHMENT_ID) + .name("XML-Daten (Originalform).xml") + .contentType(XML_CONTENT_TYPE) + .content(xmlFormString) + .build() + ), + createXmlDatenWithContent(xmlFormString)), metaAttachments.stream().map(AttachmentTestFactory::createAttachment) ).toList(); } @@ -163,7 +180,7 @@ public class AttachmentTestFactory { } @Builder - private record MetaAttachment(String id, String name, String contentType, String content, String templateId) { + public record MetaAttachment(String id, String name, String contentType, String content, String templateId) { } private static List<MetaAttachment> arrayToMetaAttachments(String[] array) { diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java index 53aa6003c9e0595b8df9e4f534ca82c2f0e91b6e..14e6051660099f272547fd68a7ec71fe265422e5 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java @@ -25,13 +25,13 @@ package de.ozgcloud.eingang.intelliform; import static de.ozgcloud.eingang.intelliform.AttachmentTestFactory.*; import static de.ozgcloud.eingang.intelliform.DepositDataTestFactory.*; +import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.io.IOException; import java.io.StringReader; import java.nio.charset.Charset; -import java.util.Collections; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; @@ -208,7 +208,11 @@ class DepositDataMapperTest { var incomingFileIds = formData.getRepresentations().stream() .map(IncomingFile::getVendorId) .toList(); - assertThat(incomingFileIds).containsExactly(XML_ATTACHMENT_ID); + assertThat(incomingFileIds).containsExactly( + XML_ATTACHMENT_ID, + XML_ROHFORM_ATTACHMENT_ID, + XML_ORIGINALFORM_ATTACHMENT_ID + ); } @DisplayName("should return with attachment groups") @@ -244,7 +248,7 @@ class DepositDataMapperTest { @DisplayName("should throw technical exception") @Test void shouldThrowTechnicalException() { - depositData = DepositDataTestFactory.create(Collections.emptyList()); + depositData = DepositDataTestFactory.create(emptyList()); assertThatThrownBy(TestMapToFormData.this::doMapping) .isInstanceOf(TechnicalException.class); @@ -257,20 +261,53 @@ class DepositDataMapperTest { } - @DisplayName("map deposit attachments to incoming files") + @DisplayName("map deposit attachments to sorted incoming files") @Nested - class TestMapDepositAttachmentsToIncomingFiles { + class TestMapDepositAttachmentsToSortedIncomingFiles { + + @DisplayName("should fail without primaryDataAttachmentId attachment") + @Test + void shouldFailWithoutPrimaryDataAttachmentIdAttachment() { + var depositData = DepositDataTestFactory.create(emptyList()); + + assertThatThrownBy(() -> mapper.mapDepositAttachmentsToSortedIncomingFiles(depositData)) + .isInstanceOf(TechnicalException.class); + } + @DisplayName("should keep entry order") @Test void shouldKeepEntryOrder() { var depositData = DepositDataTestFactory.create(ATTACHMENTS); - var incomingFileMap = mapper.mapDepositAttachmentsToIncomingFiles(depositData); + var incomingFileMap = mapper.mapDepositAttachmentsToSortedIncomingFiles(depositData); var keys = incomingFileMap.keySet().stream().toList(); assertThat(keys).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID, PNG_ATTACHMENT_ID); } + @DisplayName("should move primary attachment id to first position") + @Test + void shouldMovePrimaryAttachmentIdToFirstPosition() { + var rohformId = "XML-daten-rohform"; + var depositData = DepositDataTestFactory.create(List.of( + AttachmentTestFactory.createAttachment(MetaAttachment.builder() + .id(rohformId) + .name("XML-Daten (Rohform).xml") + .contentType(XML_CONTENT_TYPE) + .content("abc") + .build() + ), + AttachmentTestFactory.createPdf(), + AttachmentTestFactory.createXmlDaten(), + AttachmentTestFactory.createPng() + )); + + var incomingFileMap = mapper.mapDepositAttachmentsToSortedIncomingFiles(depositData); + + var keys = incomingFileMap.keySet().stream().toList(); + assertThat(keys).containsExactly(XML_ATTACHMENT_ID, rohformId, PDF_ATTACHMENT_ID, PNG_ATTACHMENT_ID); + } + @DisplayName("should keep last entry for duplicate key") @Test void shouldKeepLastEntryForDuplicateKey() { @@ -280,7 +317,7 @@ class DepositDataMapperTest { AttachmentTestFactory.createXmlDaten() )); - var incomingFileMap = mapper.mapDepositAttachmentsToIncomingFiles(depositData); + var incomingFileMap = mapper.mapDepositAttachmentsToSortedIncomingFiles(depositData); var keys = incomingFileMap.keySet().stream().toList(); assertThat(keys).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID); diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java index 524f388ca41061d7abcfe8b535d4f78853df2081..17c560fb68e7670a05e0dd8feb2102cbc15fd609 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java @@ -142,16 +142,20 @@ class FormDataEndpointITCase { return grpcEingangCaptor.getValue().getAntragsteller(); } - @DisplayName("should have one representation") + @DisplayName("should have representations") @Test - void shouldHaveOneRepresentation() { + void shouldHaveRepresentations() { sendDepositAndCaptureCreateVorgang(); var eingang = grpcEingangCaptor.getValue(); var representationVendorIds = eingang.getRepresentationsList().stream() .map(GrpcIncomingFile::getVendorId) .toList(); - assertThat(representationVendorIds).containsExactly(XML_ATTACHMENT_ID); + assertThat(representationVendorIds).containsExactly( + XML_ATTACHMENT_ID, + XML_ROHFORM_ATTACHMENT_ID, + XML_ORIGINALFORM_ATTACHMENT_ID + ); } @DisplayName("should have attachments") diff --git a/pom.xml b/pom.xml index 0ba87ca4ba4e0722f24dd73e6f0b5dff1f4947b9..50e955ac71843789ad1397c8feb2a3e5598cb06d 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <packaging>pom</packaging> <name>OZG-Cloud Eingang Manager</name> @@ -55,7 +55,7 @@ </modules> <properties> - <vorgang-manager.version>2.10.0-SNAPSHOT</vorgang-manager.version> + <vorgang-manager.version>2.10.0</vorgang-manager.version> <jsoup.version>1.14.3</jsoup.version> <xmlschema.version>2.3.0</xmlschema.version> diff --git a/router/pom.xml b/router/pom.xml index 0a6fa21b87e184f552accb38c7cf5d8ba70af6a5..205240737220e32c8408683562d5f73014c134e0 100644 --- a/router/pom.xml +++ b/router/pom.xml @@ -29,7 +29,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/semantik-adapter/pom.xml b/semantik-adapter/pom.xml index d28c38abf7daa861cd35148a8c7e730a288c7c52..6bc582e0970821647cb81f8c48de88d819972f6b 100644 --- a/semantik-adapter/pom.xml +++ b/semantik-adapter/pom.xml @@ -30,7 +30,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> </parent> <artifactId>semantik-adapter</artifactId> diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java index 47a3d8570d4b2b6c3b3b7aaa5a5d2bba58271f57..455d84f4ad8d9727137bf98d8e1e5c54cd430c6f 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java @@ -32,7 +32,10 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.router.VorgangService; import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter; +import lombok.extern.log4j.Log4j2; + +@Log4j2 @Service public class SemantikAdapter { @@ -52,7 +55,11 @@ public class SemantikAdapter { private FormData parseByEngineAdapter(FormData formData) { for (var adapter : getResponsibleEngineAdapters(formData)) { - formData = adapter.parseFormData(formData); + try { + formData = adapter.parseFormData(formData); + } catch (Exception e) { + LOG.error("beim Vorgang {} ist ein Fehler beim Parsing aufgetreten. Der Antrag wird trotzdem übernommen", formData.getId(), e); + } } return formData; } diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java index 5d7224c75ce7ff634737b79d28aeaf6e05931c6d..36a9a187a73b98daef840cd7784643867f4c7573 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java @@ -43,24 +43,15 @@ public class AfmEngineBasedAdapter implements EngineBasedSemantikAdapter { @Override public FormData parseFormData(FormData formData) { - var vorgangNummer = formData.getHeader().getVorgangNummer(); var processedFormData = intelliFormRepresentationAdapter.adaptByRepresentations(formData); for (var mapper : mappers) { processedFormData = mapper.parseFormData(processedFormData); } - return removeProcessedData(addVorgangNummer(processedFormData, vorgangNummer)); + return removeProcessedData(processedFormData); } - private FormData addVorgangNummer(FormData formData, String vorgangNummer) { - return formData.toBuilder() - .header(formData.getHeader().toBuilder() - .vorgangNummer(vorgangNummer) - .build() - ) - .build(); - } private FormData removeProcessedData(FormData formData) { return FormDataUtils.from(formData) diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java index 0f63ef3686963482d332dd1d844e75ae4d2ec865..42222ec8132a79c555967290dd1f2298ec930a18 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java @@ -67,6 +67,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper { var formHeaderBuilder = FormHeader.builder() .requestId((String) headerDataMap.get(ID)) + .vorgangNummer((String) headerDataMap.get(ID)) .createdAt(getCreatedAt(headerDataMap)) .formId((String) headerDataMap.get(FORM_ID)) .formName((String) headerDataMap.get(FORM)) @@ -105,4 +106,4 @@ class AfmHeaderMapper implements AfmEngineBasedMapper { .remove(ServiceKontoFactory.REST_RESPONSE_NAME) .build(); } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java index 9ddc1287c6c7433070c59de09264b0f8156bcc75..3e0ed8c3336fe365c2f8779cf1d6ecf98d37719f 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java @@ -1,11 +1,20 @@ package de.ozgcloud.eingang.semantik.formbased.mantelantrag; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.function.UnaryOperator; import java.util.stream.IntStream; +import jakarta.annotation.PostConstruct; + import org.apache.commons.collections.MapUtils; +import org.apache.logging.log4j.util.Strings; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @@ -32,6 +41,18 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { static final String TELEFON_FIELD = "telefon"; private final Environment environment; + private Set<String> xtaIdentifiers; + + @PostConstruct + void init() { + xtaIdentifiers = new HashSet<>(getIdentifierList()); + } + + List<String> getIdentifierList() { + return Binder.get(environment) + .bind("ozgcloud.xta.identifiers", Bindable.listOf(String.class)) + .orElseGet(Collections::emptyList); + } @Override public boolean isResponsible(FormData formData) { @@ -46,11 +67,15 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { try { return adaptFormDataWithPossibleException(formData); } catch (TechnicalException exception) { - LOG.warn("Mantelantrag is invalid: %s".formatted(exception.getMessage())); + logWarningForFailure(exception); return formData; } } + void logWarningForFailure(Exception exception) { + LOG.warn("Failed mapping Zustaendigestelle of Mantelantrag: %s".formatted(exception.getMessage())); + } + FormData adaptFormDataWithPossibleException(FormData formData) { var fieldMap = formData.getFormData(); var slotIndex = findSlotIndex(fieldMap); @@ -85,15 +110,40 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { } int findSlotIndex(Map<String, Object> fieldMap) { - var identifier = environment.getProperty("ozgcloud.xta.identifier"); + var matchingSlots = getMatchingSlots(fieldMap); + verifyOneMatchingIdentifier(matchingSlots); + return matchingSlots.getFirst(); + } + + private void verifyOneMatchingIdentifier(List<Integer> matchingSlots) { + if (matchingSlots.size() != 1) { + var message = getMultipleSlotsMessage(matchingSlots); + if (matchingSlots.isEmpty()) { + throw new TechnicalException(message); + } else { + logWarningForUnexpected(message); + } + } + } + + void logWarningForUnexpected(String message) { + LOG.warn("Unexpected Zustaendigestelle in Mantelantrag: %s".formatted(message)); + } + + String getMultipleSlotsMessage(List<Integer> matchingSlots) { + return "Found %d matching nachrichtenbroker addresses! Expected one of '%s'.".formatted(matchingSlots.size(), + Strings.join(xtaIdentifiers, ',')); + } + + private List<Integer> getMatchingSlots(Map<String, Object> fieldMap) { return IntStream.range(0, 3) - .filter(slotIndex -> getFieldByKeyOrEmpty( - fieldMap, - getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex) - ).equals(identifier) - ) - .findFirst() - .orElseThrow(() -> new TechnicalException("No matching nachrichtenbroker address '%s' found!".formatted(identifier))); + .filter(slotIndex -> xtaIdentifiers.contains(getXtaIdentifierOfSlot(fieldMap, slotIndex))) + .boxed() + .toList(); + } + + private String getXtaIdentifierOfSlot(Map<String, Object> fieldMap, int slotIndex) { + return getFieldByKeyOrEmpty(fieldMap, getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex)); } String getNameForSlotIndex(String name, int slotIndex) { diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java index 609284d26fccdb41ed91818c5df7ed0161990cdc..a99b67392b0c0cf2ce97c3230fc123280dc27857 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java @@ -100,13 +100,6 @@ class AfmEngineBasedAdapterTest { assertThat(mappedFormData.getFormData()).doesNotContainKey(AfmAntragstellerMapper.POSTFACH_ID); } - @DisplayName("should keep vorgang nummer") - @Test - void shouldKeepVorgangNummer() { - var mappedFormData = adapter.parseFormData(formData); - - assertThat(mappedFormData.getHeader().getVorgangNummer()).isEqualTo(VORGANG_NUMMER); - } } } diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java index 7af0dcd5c208e6c3989c0e8be54948e382c45ac6..80a0e966be30d910f62596d02d669cc36d5062a8 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java @@ -77,6 +77,13 @@ class AfmHeaderMapperTest { assertThat(parsedFormData.getHeader().getRequestId()).isEqualTo(AfmHeaderTestFactory.ID); } + @Test + void shouldMapVorgangNummer() { + var parsedFormData = parseFormData(); + + assertThat(parsedFormData.getHeader().getVorgangNummer()).isEqualTo(AfmHeaderTestFactory.ID); + } + @Test void shouldMapCreatedAt() { var parsedFormData = parseFormData(); @@ -189,4 +196,4 @@ class AfmHeaderMapperTest { } } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java index 9d2094d600c3eed7495003e5dfa9ba969a9b4599..a4951086c82837ebc3c01ef5f19b8833882b0e3c 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java @@ -29,7 +29,7 @@ import de.ozgcloud.eingang.semantik.enginebased.formsolutions.FormSolutionsEngin import lombok.SneakyThrows; @ActiveProfiles({ "local", "itcase" }) -@SpringBootTest(classes = Application.class, properties = { "ozgcloud.xta.identifier=afmsh:ozg-cloud-utopia-test" }) +@SpringBootTest(classes = Application.class, properties = { "ozgcloud.xta.identifiers=afmsh:ozg-cloud-utopia-test" }) public class MantelantragITCase { private static final String FILE_NAME_XDOMEA = "mantelantrag/4620-EH6C_b3c9168a-6ae9-4361-8b2f-6837bb341021_Geschaeftsgang.Geschaeftsgang.0201.xml"; diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java index f03169a6704aae741e3234b82aff876448b027d6..2cad108d2ae30f76782b0c9ddfdd934becb9be37 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java @@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Stream; @@ -17,10 +18,11 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import org.springframework.core.env.Environment; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; @@ -31,13 +33,18 @@ import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; class MantelantragZustaendigeStelleMapperTest { private final static String TARGET_OEID = "123456"; private static final String IDENTIFIER = "gea:test"; + private static final String IDENTIFIER2 = "dfad:test"; + private static final List<String> IDENTIFIERS = List.of(IDENTIFIER, IDENTIFIER2, "aa:other"); @Spy @InjectMocks private MantelantragZustaendigeStelleMapper mapper; - @Mock - private Environment environment; + @BeforeEach + void mock() { + doReturn(IDENTIFIERS).when(mapper).getIdentifierList(); + mapper.init(); + } @DisplayName("is responsible") @Nested @@ -128,6 +135,17 @@ class MantelantragZustaendigeStelleMapperTest { assertThat(resultFormData).isEqualTo(formData); } + + @DisplayName("should log warning with exception") + @Test + void shouldLogWarningWithException() { + var exception = new TechnicalException("some error"); + doThrow(exception).when(mapper).adaptFormDataWithPossibleException(formData); + + mapper.parseFormData(formData); + + verify(mapper).logWarningForFailure(exception); + } } @DisplayName("adapt form data with possible exception") @@ -275,10 +293,11 @@ class MantelantragZustaendigeStelleMapperTest { private Map<String, Object> fieldMap; + @Captor + private ArgumentCaptor<String> warningCaptor; + @BeforeEach void mock() { - when(environment.getProperty("ozgcloud.xta.identifier")).thenReturn(IDENTIFIER); - fieldMap = new HashMap<>(Map.of( getZustaendigeStelleName(1), "unknown", getZustaendigeStelleName(2), "" @@ -306,6 +325,18 @@ class MantelantragZustaendigeStelleMapperTest { assertThatThrownBy(() -> mapper.findSlotIndex(fieldMap)) .isInstanceOf(TechnicalException.class); } + + @DisplayName("should log warning if multiple slots match") + @Test + void shouldLogWarningIfMultipleSlotsMatch() { + fieldMap.put(getZustaendigeStelleName(0), IDENTIFIER2); + fieldMap.put(getZustaendigeStelleName(2), IDENTIFIER); + + mapper.findSlotIndex(fieldMap); + + verify(mapper).logWarningForUnexpected(warningCaptor.capture()); + assertThat(warningCaptor.getValue()).isEqualTo(mapper.getMultipleSlotsMessage(List.of(0, 2))); + } } @DisplayName("get name for slot index") diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml index 1abf7b15ee0077fc1c4811d6b323e709ad83e5a1..ab74074fa631daa7404959e1e05d9d4e7faed1b6 100644 --- a/src/test/helm/network_policy_test.yaml +++ b/src/test/helm/network_policy_test.yaml @@ -106,6 +106,21 @@ tests: networkPolicy: disabled: false dnsServerNamespace: test-dns-namespace + asserts: + - hasDocuments: + count: 1 + - it: test network policy dnsServerNamespace must be set message + set: + networkPolicy: + disabled: false + asserts: + - failedTemplate: + errorMessage: networkPolicy.dnsServerNamespace must be set + + - it: test network policy should be enabled by default + set: + networkPolicy: + dnsServerNamespace: test-dns-server-namespace asserts: - hasDocuments: count: 1 \ No newline at end of file diff --git a/xta-adapter/pom.xml b/xta-adapter/pom.xml index 5f8d9118152d7af5d35f78f1c168438831ccfa80..fb13d459bda7821591082501d92f4c62c47bf22d 100644 --- a/xta-adapter/pom.xml +++ b/xta-adapter/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.10.0-SNAPSHOT</version> + <version>2.11.0-SNAPSHOT</version> </parent> <artifactId>xta-adapter</artifactId> <name>Eingangs Adapter - XTA</name> diff --git a/xta-adapter/src/main/helm/templates/xta_adapter_cronjob.yaml b/xta-adapter/src/main/helm/templates/xta_adapter_cronjob.yaml index b8d0d2b9870587f17f992129bf23928c2bcb48a0..25da0415e81e4921e726683f62a7f9e1526a3d5a 100644 --- a/xta-adapter/src/main/helm/templates/xta_adapter_cronjob.yaml +++ b/xta-adapter/src/main/helm/templates/xta_adapter_cronjob.yaml @@ -63,8 +63,8 @@ spec: value: {{ (.Values.xta).server.address }} - name: ozgcloud_xta_server_protocol value: {{ (.Values.xta).server.protocol }} - - name: ozgcloud_xta_identifier - value: {{ quote (.Values.xta).identifier }} + - name: ozgcloud_xta_identifiers + value: {{ (.Values.xta).identifiers | join "," | quote }} - name: ozgcloud_xta_keystore_file value: "keystore/xta-keystore.p12" - name: ozgcloud_xta_keystore_password @@ -170,4 +170,4 @@ spec: {{- with .Values.podSecurityContext }} securityContext: {{ toYaml . | indent 12 }} - {{- end }} \ No newline at end of file + {{- end }} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java index 961231e9ad05e5ef208c05f5218493ebddd0b44e..a94e189b394b396001768386244c08a4cd750250 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java @@ -22,7 +22,11 @@ import de.ozgcloud.eingang.common.formdata.IncomingFile; public class XdomeaXMLValueReader { private static final String DATEINAME_NODE_QUERY_STRING = "//Hauptobjekt//Dateiname"; - private static final XPathExpression DATEINAME_NODE_QUERY = compileXPathExpression(DATEINAME_NODE_QUERY_STRING); + // Interpret XML-Attachments as representations + // XML filetype code: 030 (see https://www.xrepository.de/details/urn:xoev-de:xdomea:codeliste:dateiformat) + private static final String DATEINAME_NODE_FOR_XML_ANHANG_QUERY_STRING = "//Anlage//Format/Name[contains(., '030')]/..//Dateiname"; + private static final XPathExpression DATEINAME_NODE_QUERY = compileXPathExpression( + DATEINAME_NODE_QUERY_STRING + "|" + DATEINAME_NODE_FOR_XML_ANHANG_QUERY_STRING); public List<String> readRepresentationFileNames(IncomingFile xdomeaXMLFile) { return getTextsFromNodes( diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/WsHeaderAddingInterceptor.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/WsHeaderAddingInterceptor.java index a685b0a20bfc5a93b90dcd606cebb2dea31e8187..f0ae4deba9f754a290717d608921cc3acf353301 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/WsHeaderAddingInterceptor.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/WsHeaderAddingInterceptor.java @@ -1,5 +1,11 @@ package de.ozgcloud.eingang.xta; +import java.util.Objects; + +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBElement; +import jakarta.xml.bind.JAXBException; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.ws.client.WebServiceClientException; @@ -11,17 +17,12 @@ import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import eu.osci.ws._2014._10.transport.OriginatorsType; import eu.osci.ws._2014._10.transport.PartyIdentifierType; import eu.osci.ws._2014._10.transport.PartyType; -import jakarta.validation.Valid; -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBElement; -import jakarta.xml.bind.JAXBException; @Component class WsHeaderAddingInterceptor implements ClientInterceptor { @Autowired - @Valid - private XtaProperties properties; + private XtaCurrentIdentifierService xtaCurrentIdentifierService; @Override public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException { @@ -44,7 +45,10 @@ class WsHeaderAddingInterceptor implements ClientInterceptor { PartyType partyType = new PartyType(); PartyIdentifierType identifier = new PartyIdentifierType(); - identifier.setValue(properties.getIdentifier()); + identifier.setValue(Objects.requireNonNull( + xtaCurrentIdentifierService.getCurrentIdentifier(), + "Expect current identifier to be set!") + ); partyType.setIdentifier(identifier); var origin = new OriginatorsType(); diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaCurrentIdentifierService.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaCurrentIdentifierService.java new file mode 100644 index 0000000000000000000000000000000000000000..f5f6b25a9b49c40f8a088305b237570a11761b14 --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaCurrentIdentifierService.java @@ -0,0 +1,28 @@ +package de.ozgcloud.eingang.xta; + +import java.util.List; + +import jakarta.validation.Valid; + +import org.springframework.stereotype.Service; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Service +@RequiredArgsConstructor +public class XtaCurrentIdentifierService { + + @Setter + @Getter + private String currentIdentifier; + + @Valid + private final XtaProperties properties; + + public List<String> getIdentifiers() { + return properties.getIdentifiers(); + } + +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java index f81184fc20eb49e375f9d24dd9f5ce68021644c6..2cb772154e77246a41508a0116dd6db7f9cf9cae 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java @@ -1,14 +1,11 @@ package de.ozgcloud.eingang.xta; -import java.math.BigInteger; -import java.util.Optional; import java.util.stream.Stream; import jakarta.xml.bind.JAXBElement; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.Named; import eu.osci.ws._2008._05.transport.MsgStatusListType; import eu.osci.ws._2014._10.transport.MessageMetaData; @@ -26,19 +23,9 @@ interface XtaMessageMetaDataMapper { return XtaMessageId.from(id); } - @Mapping(target = "moreMessagesAvailable", source = ".", qualifiedByName = "moreMessagesAvailable") + @Mapping(target = "moreMessagesAvailable", constant = "false") XtaMessageMetaDatasAndHeader msgStatusListFromSoap(MsgStatusListTypeAndHeaderResponse statusList); - @Named("moreMessagesAvailable") - default boolean moreMessagesAvailable(MsgStatusListTypeAndHeaderResponse statusList) { - if (statusList.isNoMessageAvailable()) { - return false; - } - return Optional.ofNullable(statusList.getMessageItemsPending()) - .filter(messagesPending -> !BigInteger.ZERO.equals(messagesPending)) - .isPresent(); - } - default Stream<XtaMessageMetaData> map(JAXBElement<MsgStatusListType> msgStatusListResponse) { return msgStatusListResponse.getValue().getMessageMetaData().stream().map(this::fromSoap); } diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaProperties.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaProperties.java index 2f31999ff99e8d9e997a8e57b6ee2b6260855beb..23a4e4bcc030f56f017200536653a3fca84c44d4 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaProperties.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaProperties.java @@ -2,6 +2,7 @@ package de.ozgcloud.eingang.xta; import java.math.BigInteger; import java.net.URI; +import java.util.List; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -31,7 +32,7 @@ class XtaProperties { private KeyStore keyStore; private Actions actions; @NotEmpty - private String identifier; + private List<String> identifiers; } @Validated diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java index 19e712d4c4eb812190086b906e3c91659dea5abc..203cff44770add307aeab236f0bc9388427b9563 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java @@ -37,12 +37,20 @@ class XtaService { private XdomeaMessageDataMapper xdomeaMessageDataMapper; @Autowired private XtaIncomingFilesMapper xtaIncomingFilesMapper; + @Autowired + private XtaCurrentIdentifierService service; public Stream<FormData> getMessages() { return createXtaMessageStream().filter(this::isSupportedMessageType).map(this::getFormData); } Stream<XtaMessageMetaData> createXtaMessageStream() { + return service.getIdentifiers().stream() + .flatMap(this::createXtaMessageStreamForIdentifier); + } + + private Stream<XtaMessageMetaData> createXtaMessageStreamForIdentifier(String identifier) { + service.setCurrentIdentifier(identifier); var iterator = new XtaMessageMetadataRemoteIterator(remoteService); return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); } diff --git a/xta-adapter/src/main/resources/application-local.yml b/xta-adapter/src/main/resources/application-local.yml index 83e7b8ca8d1088a6fcbae18446b9ac917d21f942..b35125c65bce0ce95de34f97fb97c398bbcefc15 100644 --- a/xta-adapter/src/main/resources/application-local.yml +++ b/xta-adapter/src/main/resources/application-local.yml @@ -1,6 +1,7 @@ ozgcloud: xta: - identifier: gae:jens.reese@mgm-tp.com + identifiers: + - gae:jens.reese@mgm-tp.com server: address: localhost:3000 name: LI33-0005 diff --git a/xta-adapter/src/main/resources/application.yml b/xta-adapter/src/main/resources/application.yml index 53387ac656fe6347c611c311c363d971a2da055c..9ea49363440c8f86d870397d00007ff0aed7e041 100644 --- a/xta-adapter/src/main/resources/application.yml +++ b/xta-adapter/src/main/resources/application.yml @@ -6,7 +6,7 @@ logging: ozgcloud: xta: - max-list-elements: 10 + max-list-elements: 100 keystore: type: PKCS12 actions: diff --git a/xta-adapter/src/test/helm/network_policy_test.yaml b/xta-adapter/src/test/helm/network_policy_test.yaml index 0c21953e21950822c2f58361fd9081a7f0405316..74ac285893aab5f14a2b7abe6e3d5c84fd55033d 100644 --- a/xta-adapter/src/test/helm/network_policy_test.yaml +++ b/xta-adapter/src/test/helm/network_policy_test.yaml @@ -27,19 +27,26 @@ release: namespace: by-helm-test templates: - templates/network_policy.yaml -set: - networkPolicy: - dnsServerNamespace: test-dns-namespace + tests: - it: should match apiVersion + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace asserts: - isAPIVersion: of: networking.k8s.io/v1 - it: should match kind + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace asserts: - isKind: of: NetworkPolicy - it: validate metadata + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace asserts: - equal: path: metadata @@ -47,6 +54,9 @@ tests: name: network-policy-xta-adapter namespace: by-helm-test - it: validate spec + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace asserts: - equal: path: spec @@ -135,6 +145,21 @@ tests: networkPolicy: disabled: false dnsServerNamespace: test-dns-namespace + asserts: + - hasDocuments: + count: 1 + - it: test network policy dnsServerNamespace must be set message + set: + networkPolicy: + disabled: false + asserts: + - failedTemplate: + errorMessage: networkPolicy.dnsServerNamespace must be set + + - it: test network policy should be enabled by default + set: + networkPolicy: + dnsServerNamespace: test-dns-server-namespace asserts: - hasDocuments: count: 1 \ No newline at end of file diff --git a/xta-adapter/src/test/helm/xta_adapter_cronjob_basic_test.yaml b/xta-adapter/src/test/helm/xta_adapter_cronjob_basic_test.yaml index 3e4e37b8fe3f8ad0fce65be7a136aa3b8219431c..7eac13e81398613f23cc5e4dedc3309b69030c5a 100644 --- a/xta-adapter/src/test/helm/xta_adapter_cronjob_basic_test.yaml +++ b/xta-adapter/src/test/helm/xta_adapter_cronjob_basic_test.yaml @@ -60,7 +60,8 @@ tests: image.name: xta-adapter xta: schedule: "1 1 * * * *" - identifier: gae:test@ozg-sh.de + identifiers: + - gae:test@ozg-sh.de server: address: 1.2.3.4 name: test @@ -144,4 +145,4 @@ tests: path: spec.jobTemplate.spec.template.spec.containers[0].securityContext.capabilities value: drop: - - ALL \ No newline at end of file + - ALL diff --git a/xta-adapter/src/test/helm/xta_adapter_cronjob_env_test.yaml b/xta-adapter/src/test/helm/xta_adapter_cronjob_env_test.yaml index 30ad85fc12a3b14b56cecbbc4bc08b18f4d0d20a..77547800e84d3f8f60fe508c57df9e5f7d0a0de6 100644 --- a/xta-adapter/src/test/helm/xta_adapter_cronjob_env_test.yaml +++ b/xta-adapter/src/test/helm/xta_adapter_cronjob_env_test.yaml @@ -36,7 +36,9 @@ tests: set: image.name: xta-adapter xta: - identifier: gae:test@ozg-sh.de + identifiers: + - gae:test@ozg-sh.de + - afmsh:test@ozg-sh.de server: name: test address: 1.2.3.4 @@ -70,8 +72,8 @@ tests: - contains: path: spec.jobTemplate.spec.template.spec.containers[0].env content: - name: ozgcloud_xta_identifier - value: "gae:test@ozg-sh.de" + name: ozgcloud_xta_identifiers + value: "gae:test@ozg-sh.de,afmsh:test@ozg-sh.de" - contains: path: spec.jobTemplate.spec.template.spec.containers[0].env content: @@ -116,7 +118,8 @@ tests: image.name: xta-adapter env.overrideSpringProfiles: local xta: - identifier: gae:test@ozg-sh.de + identifiers: + - gae:test@ozg-sh.de server: name: test address: 1.2.3.4 @@ -196,4 +199,4 @@ tests: path: spec.jobTemplate.spec.template.spec.containers[0].env content: name: my_test_environment_name - value: "A test value" \ No newline at end of file + value: "A test value" diff --git a/xta-adapter/src/test/helm/xta_adapter_cronjob_volumes_test.yaml b/xta-adapter/src/test/helm/xta_adapter_cronjob_volumes_test.yaml index 7af81adc1e39cc206f113ab1e00415b147a65f99..352f196bf1b8a8cafccb6fa868e8da0efe595636 100644 --- a/xta-adapter/src/test/helm/xta_adapter_cronjob_volumes_test.yaml +++ b/xta-adapter/src/test/helm/xta_adapter_cronjob_volumes_test.yaml @@ -36,7 +36,8 @@ tests: set: image.name: xta-adapter xta: - identifier: gae:test@ozg-sh.de + identifiers: + - gae:test@ozg-sh.de server: name: test address: 1.2.3.4 @@ -66,7 +67,8 @@ tests: set: image.name: xta-adapter xta: - identifier: gae:test@ozg-sh.de + identifiers: + - gae:test@ozg-sh.de server: name: test address: 1.2.3.4 diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java index fdc793156871725f8e9ce415f05b652ae0dcc435..88d7d7cdae588621eee777d12af476eda7cd7abb 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.nio.charset.StandardCharsets; -import java.util.List; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.DisplayName; @@ -22,6 +21,7 @@ import lombok.SneakyThrows; class XdomeaXMLValueReaderTest { private static final String XML_FILE_NAME = "file.xml"; private static final String PDF_FILE_NAME = "file.pdf"; + private static final String XML_ATTACHMENT_FILE_NAME = "saml-attachment-file.xml"; @Spy @InjectMocks @@ -34,7 +34,7 @@ class XdomeaXMLValueReaderTest { @Mock IncomingFile incomingXmlFile; - @DisplayName("should find 'Dateiname' elements in MSR mantelantrag") + @DisplayName("should find 'Dateiname' elements and all XML-files in MSR mantelantrag") @ParameterizedTest @ValueSource(strings = { "xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml", @@ -45,12 +45,13 @@ class XdomeaXMLValueReaderTest { var xmlString = TestUtils.loadTextFile( antragXMLFilename, XML_FILE_NAME + "\n", - PDF_FILE_NAME); + PDF_FILE_NAME, + "\n" + XML_ATTACHMENT_FILE_NAME + "\n"); when(incomingXmlFile.getContentStream()).thenReturn(IOUtils.toInputStream(xmlString, StandardCharsets.UTF_8)); var names = valueReader.readRepresentationFileNames(incomingXmlFile); - assertThat(names).isEqualTo(List.of(XML_FILE_NAME, PDF_FILE_NAME)); + assertThat(names).containsExactly(XML_FILE_NAME, PDF_FILE_NAME, XML_ATTACHMENT_FILE_NAME); } } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaCurrentIdentifierServiceTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaCurrentIdentifierServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..884faf6b4dad5eda37f6be16c92b4e88cc3d095a --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaCurrentIdentifierServiceTest.java @@ -0,0 +1,44 @@ +package de.ozgcloud.eingang.xta; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; + +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.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +class XtaCurrentIdentifierServiceTest { + + private static final String IDENTIFIER1 = "identifier1"; + private static final String IDENTIFIER2 = "identifier2"; + private static final List<String> IDENTIFIERS = List.of(IDENTIFIER1, IDENTIFIER2); + + @Spy + @InjectMocks + private XtaCurrentIdentifierService service; + + @Mock + private XtaProperties properties; + + @DisplayName("get identifiers") + @Nested + class TestGetIdentifiers { + @BeforeEach + void mock() { + when(properties.getIdentifiers()).thenReturn(IDENTIFIERS); + } + + @DisplayName("should return") + @Test + void shouldReturn() { + assertThat(service.getIdentifiers()).isEqualTo(IDENTIFIERS); + } + } + +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java index 43d08f9a67f8f0954290dc1b81d5f2a2b4c5d4b2..6b3bcd60c522a6ceb8a602486baa69b51a269c8c 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java @@ -138,15 +138,30 @@ class XtaITCase { assertThat(organisationseinheitenId).isEqualTo("9795669"); } - @DisplayName("should have vorgang nummer") - @TestZipFileNames - void shouldHaveVorgangNummer(String zipFileName) { + @DisplayName("should have generated vorgang nummer for dFoerdermittel") + @Test + void shouldHaveVorgangsnummer() { + mockNachrichtenBroker("dfoerdermittel_with_anlage.zip"); + + runner.runGetXtaMessages(); + + var vorgangsNummer = captureEingang() + .getHeader() + .getVorgangNummer(); + assertThat(vorgangsNummer).hasSameSizeAs("4627-TY3X"); + } + + @DisplayName("should have vorgang nummer for AFM") + @TestZipFileNamesFromAFM + void shouldHaveVorgangsnummerForAfm(String zipFileName) { mockNachrichtenBroker(zipFileName); runner.runGetXtaMessages(); - var vorgangNummer = captureEingang().getHeader().getVorgangNummer(); - assertThat(vorgangNummer).hasSize(9); + var vorgangsNummer = captureEingang() + .getHeader() + .getVorgangNummer(); + assertThat(vorgangsNummer).hasSameSizeAs("20240404370530710707"); } @DisplayName("should use xta vorgangsnummer for FIM") @@ -241,6 +256,18 @@ class XtaITCase { @interface TestZipFileNamesWithoutPdf { } + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "mantelantrag_without_anlage.zip", + "brauchtumsfeuer_without_anlage.zip", + "mantelantrag_with_anlage.zip", + "brauchtumsfeuer_with_anlage.zip", + }) + @interface TestZipFileNamesFromAFM { + } + @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @ParameterizedTest diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java index 0b26412b73ffb000e3214c0e73fcddce166f6372..26f1ef8d1c76ea3a17eb9b6031c3df7d5d1e54d9 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.*; import java.math.BigInteger; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; @@ -14,55 +15,27 @@ class XtaMessageMetaDataMapperTest { @Spy private final XtaMessageMetaDataMapper mapper = Mappers.getMapper(XtaMessageMetaDataMapper.class); + @DisplayName("msg status list from soap") @Nested - class TestMoreMessagesAvailable { + class TestMsgStatusListFromSoap { @Test - void shouldReturnFalseOnNoMessagesAvailable() { + void shouldMap() { + var response = MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().build(); - var response = mapper.moreMessagesAvailable(buildWithNoMessageAvailable()); + var result = mapper.msgStatusListFromSoap(response); - assertThat(response).isFalse(); - } - - private MsgStatusListTypeAndHeaderResponse buildWithNoMessageAvailable() { - return MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().noMessageAvailable(true).build(); - } - - @Test - void shouldReturnFalseOnPendingMessagesNull() { - - var response = mapper.moreMessagesAvailable(buildPendingMessagesNull()); - - assertThat(response).isFalse(); - } - - private MsgStatusListTypeAndHeaderResponse buildPendingMessagesNull() { - return MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().messageItemsPending(null).build(); + assertThat(result).isNotNull(); } + @DisplayName("should set moreMessagesAvailable to false") @Test - void shouldReturnFalseOnNoMessagesPending() { + void shouldSetMoreMessagesAvailableToFalse() { + var response = MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().build(); - var response = mapper.moreMessagesAvailable(buildWithoutPendingMessages()); - - assertThat(response).isFalse(); - } - - private MsgStatusListTypeAndHeaderResponse buildWithoutPendingMessages() { - return MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().messageItemsPending(null).build(); - } - - @Test - void shouldReturnTrueOnMessagesPending() { - - var response = mapper.moreMessagesAvailable(buildWithPendingMessages()); - - assertThat(response).isTrue(); - } + var result = mapper.msgStatusListFromSoap(response); - private MsgStatusListTypeAndHeaderResponse buildWithPendingMessages() { - return MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().messageItemsPending(BigInteger.ONE).build(); + assertThat(result.isMoreMessagesAvailable()).isFalse(); } } } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java index d0e4d3c504fe095b16d7b7563be4644e9d14c2e4..0d05f6c1ae589350c8bdca53632a13844c2ead6b 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java @@ -23,7 +23,9 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; +import de.ozgcloud.eingang.xdomea.XdomeaMessageData; import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper; +import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory; class XtaServiceTest { @@ -46,6 +48,9 @@ class XtaServiceTest { @Mock private XdomeaMessageDataMapper xdomeaMessageDataMapper; + @Mock + private XtaCurrentIdentifierService currentIdentifierService; + @Nested class TestGetMessagesAsFormData { @@ -275,4 +280,46 @@ class XtaServiceTest { } } + @DisplayName("create XTA message stream") + @Nested + class TestCreateXtaMessageStream { + private static final List<String> XTA_IDENTIFIERS = List.of("XTA_IDENTIFIER", "XTA_IDENTIFIER2"); + + @Captor + private ArgumentCaptor<String> identifierCaptor; + + @BeforeEach + void mock() { + when(remoteService.getMessagesMetadata()) + .thenReturn(XtaMessageMetaDatasAndHeaderTestFactory.create()) + .thenReturn(XtaMessageMetaDatasAndHeaderTestFactory.create()); + when(currentIdentifierService.getIdentifiers()).thenReturn(XTA_IDENTIFIERS); + } + + @DisplayName("should return") + @Test + void shouldReturn() { + var result = service.createXtaMessageStream().toList(); + + assertThat(result).isEqualTo(getExpectedMessages()); + } + + private List<XtaMessageMetaData> getExpectedMessages() { + return Stream.concat( + XtaMessageMetaDatasAndHeaderTestFactory.create().getMessages(), + XtaMessageMetaDatasAndHeaderTestFactory.create().getMessages() + ).toList(); + } + + @DisplayName("should call set current identifier") + @Test + void shouldCallSetCurrentIdentifier() { + service.createXtaMessageStream().toList(); + + verify(currentIdentifierService, times(2)) + .setCurrentIdentifier(identifierCaptor.capture()); + assertThat(identifierCaptor.getAllValues()).isEqualTo(XTA_IDENTIFIERS); + } + } + } diff --git a/xta-adapter/src/test/resources/application-itcase.yml b/xta-adapter/src/test/resources/application-itcase.yml index 99b88fbe12ffdb4562dc264c08595afde1b9092a..e4f04915dcad084966187e831830afba2e8da1c1 100644 --- a/xta-adapter/src/test/resources/application-itcase.yml +++ b/xta-adapter/src/test/resources/application-itcase.yml @@ -1,6 +1,7 @@ ozgcloud: xta: - identifier: afmsh:010600000000_Online-Dienste + identifiers: + - afmsh:010600000000_Online-Dienste server: address: localhost:3000 name: LI33-0005 diff --git a/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml index 28200a104f3cb7ded5851105ad2d9fd80034bc3c..06068ed7f11a66915d42260f0bb8c10774965b0f 100644 --- a/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml +++ b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -104,4 +104,35 @@ </Verfuegung> </Beteiligungsschritt> </ExternerGeschaeftsgang> + <Anlage> + <Dokument> + <Identifikation> + <ID>1d8ca22a-9d20-4507-aa5e-b764bb5642f0</ID> + </Identifikation> + <Typ>Anlage</Typ> + <Version> + <Nummer>1</Nummer> + <Format> + <Name listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" xsi:type="DateiformatCodeType"> + <code xmlns="">030</code> + <name xmlns="">xml-eXtensible Markup Language</name> + </Name> + <Version>0.0</Version> + <Primaerdokument> + <Dateiname>%s</Dateiname> + </Primaerdokument> + </Format> + <Format> + <Name listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" xsi:type="DateiformatCodeType"> + <code xmlns="">018</code> + <name xmlns="">pdf-Portable Document Format</name> + </Name> + <Version>0.0</Version> + <Primaerdokument> + <Dateiname>anhang.pdf</Dateiname> + </Primaerdokument> + </Format> + </Version> + </Dokument> + </Anlage> </Geschaeftsgang.Geschaeftsgang.0201> diff --git a/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml index 349a7a5c3a2406981d48091a319a7aa8f63b16f0..7bed65db92efc3fb0109240b75e19cef0ba7023f 100644 --- a/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml +++ b/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -96,4 +96,37 @@ </xdomea:Verfuegung> </xdomea:Beteiligungsschritt> </xdomea:ExternerGeschaeftsgang> + <xdomea:Anlage> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>1d8ca22a-9d20-4507-aa5e-b764bb5642f0</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Typ>Anlage</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Format> + <xdomea:Name codeName="xml - eXtensible Markup Language" + codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" + languageCode="de" codelistName="Dateiformat">030 + </xdomea:Name> + <xdomea:Version>0.0</xdomea:Version> + <xdomea:Primaerdokument> + <xdomea:Dateiname>%s</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + <xdomea:Version> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Format> + <xdomea:Name codeName="pdf - Portable Document Format" codelistAgencyName="AG XDOMEA des KoopA ADV" + codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Dateiformat">018 + </xdomea:Name> + <xdomea:Version>0.0</xdomea:Version> + <xdomea:Primaerdokument> + <xdomea:Dateiname>anhang.pdf</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Anlage> </xdomea:Geschaeftsgang.Geschaeftsgang.0201>