diff --git a/common/pom.xml b/common/pom.xml index 308eb1f1cdab2265e2c4e0d650f5f80a21b3e182..0d014f643b4e14bc198be9cf3fee612e17f42ee1 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> <artifactId>common</artifactId> diff --git a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java index 44a034a849e5b5a34f20f4a369122aac82cf6d80..474be54dfd8c56eb60f5d9b2fb535742273f0fe8 100644 --- a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java +++ b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java @@ -26,6 +26,7 @@ package de.ozgcloud.eingang.common.formdata; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import jakarta.validation.constraints.NotNull; @@ -62,4 +63,19 @@ public class FormData { @Singular private List<IncomingFile> representations; + private FormDataControl control; + + @Getter + @Builder + public static class FormDataControl { + private Optional<Representations> representations; + } + + @Getter + @Builder + public static class Representations { + private String primaryFormDataRepresentation; + private String primaryFormDataPdfRepresentation; + private String formDataModell; + } } diff --git a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormHeader.java b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormHeader.java index 24b0e72766bf67f7702ea1974e7b2a2f69f1f22d..868b83b069bace798dc63571766f04308188d53f 100644 --- a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormHeader.java +++ b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormHeader.java @@ -43,6 +43,8 @@ public class FormHeader { private String formId; private String formName; private String sender; + + private String channel; private String formEngineName; private ServiceKonto serviceKonto; diff --git a/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java b/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java index ab2f7588d424a1358a4d8bcd01d360e705917e86..6cce21a27b16bcf67062209a83427366ba35b583 100644 --- a/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java +++ b/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java @@ -1,9 +1,14 @@ package de.ozgcloud.eingang.common.formdata; +import java.util.EnumSet; import java.util.List; +import org.apache.commons.lang3.StringUtils; + +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Singular; @Getter @@ -22,4 +27,23 @@ public class ServiceKonto { private String version; private PostfachAddressIdentifier identifier; } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + public enum TrustLevel { + + LEVEL_1("STORK-QAA-Level-1"), + LEVEL_2("STORK-QAA-Level-2"), + LEVEL_3("STORK-QAA-Level-3"), + LEVEL_4("STORK-QAA-Level-4"); + + private final String value; + + public static boolean exists(String trustLevelValue) { + if (StringUtils.isBlank(trustLevelValue)) { + return false; + } + return EnumSet.allOf(TrustLevel.class).stream().map(trustLevel -> trustLevel.value).anyMatch(trustLevelValue::equalsIgnoreCase); + } + } + } \ No newline at end of file diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/TrustLevelTest.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/TrustLevelTest.java new file mode 100644 index 0000000000000000000000000000000000000000..93c12966a7e2b57ae3053bb583e585d6683025d9 --- /dev/null +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/TrustLevelTest.java @@ -0,0 +1,32 @@ +package de.ozgcloud.eingang.common.formdata; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; + +import de.ozgcloud.eingang.common.formdata.ServiceKonto.TrustLevel; + +class TrustLevelTest { + + @DisplayName("should return true when") + @ParameterizedTest(name = "trust level is {0}") + @ValueSource(strings = {"STORK-QAA-Level-1", "STORK-QAA-Level-2", "STORK-QAA-Level-3", "STORK-QAA-Level-4"}) + void shouldReturnTrue(String trustLevel) { + var isValid = TrustLevel.exists(trustLevel); + + assertThat(isValid).isTrue(); + } + + @DisplayName("should return false when") + @ParameterizedTest(name = "trust level is \"{0}\"") + @NullAndEmptySource + @ValueSource(strings = {"STORK-QAA-Level-0", "unexpected"}) + void shouldReturnFalse(String trustLevel) { + var isValid = TrustLevel.exists(trustLevel); + + assertThat(isValid).isFalse(); + } +} \ No newline at end of file diff --git a/enterprise-adapter/pom.xml b/enterprise-adapter/pom.xml index 2198068056ad1def403e4896c8ed3f195dedc416..86cd361960b46a6f76dc40a06e552d3fe0392375 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> </parent> <artifactId>enterprise-adapter</artifactId> <name>EM - Enterprise Interface Adapter</name> diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/EnterpriseAdapterConfiguration.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/EnterpriseAdapterConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..0ac48af3cdb7119aa93b35dc674bdfd31458502e --- /dev/null +++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/EnterpriseAdapterConfiguration.java @@ -0,0 +1,19 @@ +package de.ozgcloud.eingang.enterprise; + +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; +import de.ozgcloud.eingang.semantik.enginebased.a12.A12EngineBasedAdapter; +import de.ozgcloud.eingang.semantik.enginebased.a12.A12EngineBasedMapper; + +@Configuration +class EnterpriseAdapterConfiguration { + + @Bean + EngineBasedSemantikAdapter engineBasedAdapter(List<A12EngineBasedMapper> mapper) { + return new A12EngineBasedAdapter(mapper); + } +} diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java index 20b6563bd1a8f6dd48a55340a4f803b05b9e542d..66431be6bf498d341a7b10ca8d38c7de46f42da3 100644 --- a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java +++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java @@ -1,8 +1,12 @@ package de.ozgcloud.eingang.enterprise.entry; import java.io.IOException; +import java.io.InputStream; import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.Objects; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; @@ -13,8 +17,13 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.multipart.MultipartFile; +import de.ozgcloud.common.binaryfile.TempFileUtils; +import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; import de.ozgcloud.eingang.enterprise.entry.EntryResponse.ResponseVorgang; import de.ozgcloud.eingang.semantik.SemantikAdapter; @@ -25,6 +34,7 @@ import de.ozgcloud.eingang.semantik.SemantikAdapter; public class EntryController { private static final String STARTING_STATUS = "NEU"; + private static final String OTHER_FILE_GROUP_NAME = "Sonstige"; @Autowired private EntryDataMapper mapper; @@ -36,9 +46,14 @@ public class EntryController { @ResponseStatus(HttpStatus.ACCEPTED) @PostMapping(consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE) - public EntryResponse receiveAntrag(@RequestPart Resource formData) throws IOException { + public EntryResponse receiveAntrag(@RequestPart("formData") Resource formData, + @RequestPart(name = "representation", required = false) Collection<MultipartFile> representations, + @RequestPart(name = "attachment", required = false) Collection<MultipartFile> attachment) + throws IOException { var mapped = mapper.mapEntryData(formData.getInputStream()); mapped = addVorgangNummer(mapped); + mapped = addRepresentations(representations, mapped); + mapped = addAttachments(attachment, mapped); var vorgangId = semantikAdapter.processFormData(mapped); @@ -50,6 +65,50 @@ public class EntryController { return formData.toBuilder().header(header).build(); } + private FormData addRepresentations(Collection<MultipartFile> representations, FormData formData) { + if (Objects.isNull(representations)) { + return formData; + } + + var builder = formData.toBuilder(); + representations.stream().map(this::buildIncomingFile).forEach(builder::representation); + return builder.numberOfRepresentations(representations.size()).build(); + } + + FormData addAttachments(Collection<MultipartFile> attachments, FormData formData) { + if (CollectionUtils.isEmpty(attachments)) { + return formData; + } + + IncomingFileGroup group = buildSonstigeGroup(attachments); + return formData.toBuilder().attachment(group).numberOfAttachments(group.getFiles().size()).build(); + } + + private IncomingFileGroup buildSonstigeGroup(Collection<MultipartFile> attachments) { + var builder = IncomingFileGroup.builder().name(OTHER_FILE_GROUP_NAME); + attachments.stream().map(this::buildIncomingFile).forEach(builder::file); + return builder.build(); + } + + private IncomingFile buildIncomingFile(MultipartFile multipartFile) { + InputStream inStream = getInputStream(multipartFile); + + return IncomingFile.builder() + .name(multipartFile.getOriginalFilename()) + .contentType(multipartFile.getContentType()) + .size(multipartFile.getSize()) + .file(TempFileUtils.writeTmpFile(inStream)) + .build(); + } + + private InputStream getInputStream(MultipartFile multipartFile) { + try { + return multipartFile.getInputStream(); + } catch (IOException e) { + throw new TechnicalException("Error reading incoming multipart File.", e); + } + } + EntryResponse buildResponse(FormData formData, String vorgangId) { return EntryResponse.builder() .transactionId(formData.getHeader().getRequestId()) diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java index 619986d45e4ad01ac04dd5df7979adaea0a907a5..a25b788b39590e1f86375981374c668dd1319e37 100644 --- a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java +++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java @@ -29,12 +29,22 @@ public class EntryData { private String formName; private Servicekonto serviceKonto; + private Representations representations; + @Builder @Getter @Jacksonized public static class ResultEndpoint { private String address; } + + @Builder + @Getter + @Jacksonized + public static class Representations { + private String formData; + private String formDataModell; + } } @Builder diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java index 4ecc509d8213d160b34c0af4e8bfc5c98afebbe3..b671d184d9f6a90939b2d4e10be29722cb365e3f 100644 --- a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java +++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; @@ -11,6 +12,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; import de.ozgcloud.eingang.common.formdata.FormHeader; import de.ozgcloud.eingang.common.formdata.PostfachAddressIdentifier; import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress; @@ -37,14 +39,23 @@ public interface FormDataMapper { @Mapping(target = "zustaendigeStelle", source = "control.zustaendigeStelle") FormData mapEntryData(EntryData entryData); + default <T> Optional<T> mapOptional(T obj) { + return Optional.ofNullable(obj); + } + @Mapping(target = "vorgangNummer", ignore = true) @Mapping(target = "createdAt", ignore = true) - @Mapping(target = "formEngineName", constant = "EnterpriseSoftware") + @Mapping(target = "channel", constant = "B2G") + @Mapping(target = "formEngineName", constant = "A12") // TODO @Mapping(target = "requestId", source = "transactionId") @Mapping(target = "sender", ignore = true) // TODO fill from authentication @Mapping(target = "serviceKonto.postfachAddresses", ignore = true) FormHeader mapHeader(EntryData.ControlData controlData); + @Mapping(target = "primaryFormDataPdfRepresentation", ignore = true) + @Mapping(target = "primaryFormDataRepresentation", source = "formData") + Representations mapRepresentations(EntryData.ControlData.Representations representations); + default ZustaendigeStelle fromId(String organisationsEinheitenId) { return ZustaendigeStelle.builder().organisationseinheitenId(organisationsEinheitenId).build(); } diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/ControlDataTestFactory.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/ControlDataTestFactory.java index d2b7a571e5d619310929af44261dbf1be7347122..ece8a0aaf9f4f39a2044d8af1590f4b2ad638579 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/ControlDataTestFactory.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/ControlDataTestFactory.java @@ -1,6 +1,7 @@ package de.ozgcloud.eingang.enterprise.entry; import de.ozgcloud.eingang.enterprise.entry.EntryData.ControlData; +import de.ozgcloud.eingang.enterprise.entry.EntryData.ControlData.Representations; import de.ozgcloud.eingang.enterprise.entry.EntryData.ControlData.ResultEndpoint; public class ControlDataTestFactory { @@ -26,6 +27,10 @@ public class ControlDataTestFactory { .resultEndpoint(ResultEndpoint.builder().address(RESULT_ENDPOIN_ADDRESS).build()) .formId(FORM_ID) .formName(NAME) - .serviceKonto(ServicekontoTestFactory.create()); + .serviceKonto(ServicekontoTestFactory.create()) + .representations(Representations.builder() + .formData(FormDataControlTestFactory.PRIMARY_FORM_DATA_REPRESENTATION) + .formDataModell(FormDataControlTestFactory.FORM_DATA_MODELL) + .build()); } } diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java index 026a2dba306f8d22f02b5bf4ede8c5ab64322e4b..86d4309910b98191d19bfc9a33b8b97fed0f33c9 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java @@ -1,14 +1,19 @@ package de.ozgcloud.eingang.enterprise.entry; +import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @@ -16,6 +21,7 @@ import org.springframework.test.web.servlet.ResultActions; import de.ozgcloud.common.test.ITCase; import de.ozgcloud.common.test.TestUtils; +import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.router.VorgangService; import lombok.SneakyThrows; @@ -40,7 +46,60 @@ class EnterpriseEntryITCase { @SneakyThrows private ResultActions doPostRequest() { return mockMvc.perform(multipart("/antrag") - .file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/simple.json").getBytes()))) + .file(new MockMultipartFile("formData", "simple.json", MediaType.APPLICATION_JSON.toString(), + TestUtils.loadTextFile("request/simple.json").getBytes()))) .andExpect(status().is2xxSuccessful()); } + + @Nested + class A12Entry { + + @Captor + private ArgumentCaptor<FormData> formDataCaptor; + + @Test + void shouldCreateVorgang() { + var formData = doPostRequest(); + + assertThat(formData).isNotNull(); + } + + void shouldHaveNoOfRepresentations() { + var formData = doPostRequest(); + + assertThat(formData.getNumberOfRepresentations()).isEqualTo(2); + } + + @Test + void shouldHaveFormData() { + var formData = doPostRequest(); + + assertThat(formData.getFormData()).containsKeys("Haushaltsjahr", "Anlage_1", "Anlage_2"); + } + + @Test + void shouldHaveMukServiceKonto() { + var formData = doPostRequest(); + + assertThat(formData.getHeader().getServiceKonto().getType()).isEqualTo("MUK"); + } + + @SneakyThrows + private FormData doPostRequest() { + mockMvc.perform(multipart("/antrag") + .file(buildJsonFileMock("formData", "a12_entry.json")) + .file(buildJsonFileMock("representation", "document_JaS.json")) + .file(buildJsonFileMock("representation", "jugendsozialarbeit_an_schulen-DM.json"))) + .andExpect(status().is2xxSuccessful()); + + verify(vorgangService).createVorgang(formDataCaptor.capture()); + return formDataCaptor.getValue(); + } + + } + + private MockMultipartFile buildJsonFileMock(String name, String origName) { + var fileToLoad = "request/%s".formatted(origName); + return new MockMultipartFile(name, origName, MediaType.APPLICATION_JSON.toString(), TestUtils.loadTextFile(fileToLoad).getBytes()); + } } diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java index 6e3bcb26596a888594f0560cf7bc5cea7c963ba2..5d1515ab2e9d1b8b2d765e1e16408273803fc3da 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java @@ -1,12 +1,15 @@ package de.ozgcloud.eingang.enterprise.entry; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.InstanceOfAssertFactories.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.io.InputStream; +import java.util.Collections; +import java.util.List; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +31,7 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.FormHeader; import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; import de.ozgcloud.eingang.semantik.SemantikAdapter; import lombok.SneakyThrows; @@ -56,7 +60,7 @@ class EntryControllerTest { class ReceiveAntrag { private final FormHeader header = FormHeaderTestFactory.createBuilder().vorgangNummer(null).build(); - private final FormData formData = FormDataTestFactory.createBuilder().header(header).build(); + private final FormData formData = FormDataTestFactory.createBuilder().header(header).clearAttachments().clearRepresentations().build(); @Captor private ArgumentCaptor<InputStream> streamCaptor; @@ -108,7 +112,7 @@ class EntryControllerTest { @Test @SneakyThrows void shouldReturnResponse() { - var response = controller.receiveAntrag(mock(Resource.class)); + var response = controller.receiveAntrag(mock(Resource.class), Collections.emptyList(), Collections.emptyList()); assertThat(response).isSameAs(this.response); } @@ -119,6 +123,112 @@ class EntryControllerTest { .file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/simple.json").getBytes()))) .andExpect(status().is2xxSuccessful()); } + + @Nested + class WithRepresentations { + + @Captor + private ArgumentCaptor<FormData> formDataCaptor; + + @Test + void shouldAddRepresentations() { + var formData = doPostRequest(); + + assertThat(formData.getRepresentations()).hasSize(2); + } + + @Test + void shouldSetNumberOfRepresentations() { + var formData = doPostRequest(); + + assertThat(formData.getNumberOfRepresentations()).isEqualTo(2); + } + + @SneakyThrows + private FormData doPostRequest() { + mockMvc.perform(multipart("/antrag") + .file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/a12_entry.json").getBytes())) + .file(new MockMultipartFile("representation", TestUtils.loadTextFile("request/document_JaS.json").getBytes())) + .file(new MockMultipartFile("representation", + TestUtils.loadTextFile("request/jugendsozialarbeit_an_schulen-DM.json").getBytes()))) + .andExpect(status().is2xxSuccessful()); + + verify(semantikAdapter).processFormData(formDataCaptor.capture()); + return formDataCaptor.getValue(); + } + } + + @Nested + class WithAttachments { + @Test + void shouldAddAttachments() { + var formData = doPostRequest(); + + assertThat(formData.getAttachments()).hasSize(1).first().extracting(IncomingFileGroup::getFiles).asInstanceOf(LIST).hasSize(1); + } + + @Test + void shouldSetNumberOfAttachments() { + var formData = doPostRequest(); + + assertThat(formData.getNumberOfAttachments()).isEqualTo(1); + } + + @SneakyThrows + private FormData doPostRequest() { + mockMvc.perform(multipart("/antrag") + .file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/a12_entry.json").getBytes())) + .file(new MockMultipartFile("attachment", TestUtils.loadTextFile("request/document_JaS.json").getBytes()))) + .andExpect(status().is2xxSuccessful()); + + verify(semantikAdapter).processFormData(formDataCaptor.capture()); + return formDataCaptor.getValue(); + } + + } + + } + + @Nested + class TestAddAttachments { + + private MockMultipartFile file = new MockMultipartFile("attachment", TestUtils.loadTextFile("request/document_JaS.json").getBytes()); + + @Test + void shouldIgnoreNullCollection() { + var formData = FormDataTestFactory.create(); + + var result = controller.addAttachments(null, formData); + + assertThat(result).isSameAs(formData); + } + + @Test + void shouldIgnoreEmptyCollection() { + var formData = FormDataTestFactory.create(); + + var result = controller.addAttachments(Collections.emptyList(), formData); + + assertThat(result).isSameAs(formData); + } + + @Test + void shouldAddToSonstigeGroup() { + var formData = FormDataTestFactory.createBuilder().clearAttachments().build(); + + var result = controller.addAttachments(List.of(file), formData); + + assertThat(result.getAttachments()).hasSize(1).first().extracting(IncomingFileGroup::getName).isEqualTo("Sonstige"); + } + + @Test + void shouldAddFiles() { + var formData = FormDataTestFactory.createBuilder().clearAttachments().build(); + + var result = controller.addAttachments(List.of(file), formData); + + assertThat(result.getAttachments()).hasSize(1).first().extracting(IncomingFileGroup::getFiles).asInstanceOf(LIST).hasSize(1); + } } @Nested diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java index de9426a23d153faf8c7c33ea35ae3087fcb16fdc..797f0ec78434b82586b90e31cc2c6932188d744c 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java @@ -46,7 +46,9 @@ class EntryDataMapperTest { void shouldReadJson() { var read = mapper.readRequest(jsonInput); - assertThat(read).usingRecursiveComparison().isEqualTo(EntryDataTestFactory.create()); + assertThat(read).usingRecursiveComparison() + .isEqualTo(EntryDataTestFactory.createBuilder().control(ControlDataTestFactory.createBuilder().representations(null).build()) + .build()); } } diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataControlTestFactory.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataControlTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..fe7e1a060b7216a5f466a5fcbd272d5bedbe1c33 --- /dev/null +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataControlTestFactory.java @@ -0,0 +1,25 @@ +package de.ozgcloud.eingang.enterprise.entry; + +import java.util.Optional; + +import de.ozgcloud.eingang.common.formdata.FormData.FormDataControl; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; + +public class FormDataControlTestFactory { + + public static final String PRIMARY_FORM_DATA_REPRESENTATION = "document_JaS.json"; + public static final String PRIMARY_FORM_DATA_PDF_REPRESENTATION = "document.pdf"; + public static final String FORM_DATA_MODELL = "jugendsozialarbeit_an_schulen-DM.json"; + + public static FormDataControl create() { + return createBuilder().build(); + } + + public static FormDataControl.FormDataControlBuilder createBuilder() { + return FormDataControl.builder() + .representations(Optional.of(Representations.builder() + .primaryFormDataRepresentation(PRIMARY_FORM_DATA_REPRESENTATION) + .formDataModell(FORM_DATA_MODELL) + .build())); + } +} diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapperTest.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapperTest.java index f725885390ee66c6da08232950680b787884562c..3b4d6691965f4a8cc9dc273dd4b3be6ab7409bcb 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapperTest.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapperTest.java @@ -23,4 +23,14 @@ class FormDataMapperTest { } } + @Nested + class TestMapRepresentations { + @Test + void shouldMapRepresentations() { + var mapped = mapper.mapRepresentations(ControlDataTestFactory.create().getRepresentations()); + + assertThat(mapped).usingRecursiveComparison().isEqualTo(FormDataControlTestFactory.create().getRepresentations().get()); + } + } + } diff --git a/enterprise-adapter/src/test/resources/request/a12_entry.json b/enterprise-adapter/src/test/resources/request/a12_entry.json new file mode 100644 index 0000000000000000000000000000000000000000..553b82dc2c082291705ae961c432a89e351e9ded --- /dev/null +++ b/enterprise-adapter/src/test/resources/request/a12_entry.json @@ -0,0 +1,27 @@ +{ + "control": { + "transactionId": "4e7a6ae7-4d0f-444d-8971-7cfc051c9924", + "zustaendigeStelle": "248240886", + "leikaIds": [ + "99108011000000", + "99108011153000" + ], + "resultEndpoint": { + "address": "https://idalabs.de/backend/api" + }, + "formId": "KFAS_LIVE_KI_10_Haltverbot_befristet", + "name": "Anmeldung zur Einrichtung einer zeitlich befristeten Haltverbotszone gem. § 45 Abs. 1 Straßenverkehrsordnung (StVO)", + "serviceKonto": { + "type": "MUK", + "postfachAddress": { + "identifier": "e155fcdc-a73e-4ae2-b148-b02e02331ebb", + "type": "unternehmen" + } + }, + "representations": { + "formData": "document_JaS.json", + "modell": "jugendsozialarbeit_an_schulen-DM.json" + } + }, + "formData": [] +} \ No newline at end of file diff --git a/enterprise-adapter/src/test/resources/request/document_JaS.json b/enterprise-adapter/src/test/resources/request/document_JaS.json new file mode 100644 index 0000000000000000000000000000000000000000..1245a457921a4f4d8f78de3265ec602ecf21bd38 --- /dev/null +++ b/enterprise-adapter/src/test/resources/request/document_JaS.json @@ -0,0 +1,99 @@ +{ + "root": { + "Haushaltsjahr": "2024", + "Anlage_2": { + "Finanzierungsplan": { + "Insgesamt_Finanzierungsplan": 117450, + "Eigenmittel_von_Hundert": 1.5, + "Eigenmittel_Betrag": 1500, + "Zuwendungen_kirchlicher_Stellen": 0, + "Angabe_der_kirchlichen_Stelle": "-", + "Zuwendungen_Bezirk": 600, + "Beantragter_Zuschuss": 700, + "Erlaeuterungen_Finanzierungsplan": "Das passt doch schon so.", + "Zuwendung_kommunale": { + "Gemeinden": "Eselstadt", + "Zuwendung_Gemeinden": 100000, + "Landkreise": "Esellandkreis", + "Zuwendung_Landkreise": 10000 + }, + "Sonstige_oeffentliche_Mittel": { + "Angabe_Bewilligungstelle_sonsitge_oeffentl_Mittel": "Amt für Eselangelegenheiten", + "Betrag_sonsitge_oeffentl_Mittel": 5000 + }, + "Fremdmittel": { + "Angabe_Bewilligungstelle_Fremdmittel": "Eselförderverband", + "Betrag_Fremdmittel": 250 + } + }, + "Kostenplan": { + "Insgesamt_Kostenplan": 175003, + "Personalkosten_JaS": 100000, + "Personalkosten_Sonstige": 15000, + "Sachkosten": 60000, + "Sonstige_Kosten": 3, + "Erlaeuterungen_Kostenplan": "Eseltrainer sind eben teuer." + } + }, + "Angaben_Antragssteller": { + "Name_Bezeichnung": "Eselschule Eselstadt", + "Strasse_Hausnummer": "Eselweg 12", + "PLZ": "01234", + "Ort": "Eselstadt", + "Telefon": "01234-5678", + "Fax": "01234-5679", + "EMail": "esel@esel.esel", + "Verantwortlicher_Vertreter": "Eva Esel", + "Zustaendiger_Sachbearbeiter": "Miriam Maultier", + "Bankverbindung": { + "Kreditinstitut": "Eselbank", + "Kontoinhaber": "Eselschule Eselstadt", + "IBAN": "DE62500105179236738719", + "BIC": "TDLJCAC5JPS" + }, + "Zustaendiger_Spitzenverband": { + "Bezeichnung": "Schulverband für liebe Esel", + "Strasse_Hausnummer": "Eselstraße 5", + "PLZ": "01234", + "Ort": "Eselstadt" + } + }, + "Angaben_zum_Projekt": { + "Bezeichnung": "Wandern mit lieben Eseln", + "Beginn_der_Massnahme": "2024-03-01", + "Verantwortlicher_Sachbearbeiter": "Eduard Esel", + "Strasse_Hausnummer": "Eselallee 77", + "PLZ": "01234", + "Ort": "Eselstadt", + "Telefon": "01234-9876", + "Fax": "01234-9875", + "EMail": "esel2@esel.esel" + }, + "Anlage_1": { + "Personalkosten": [ + { + "Lfd_Nr": 1, + "Name": "Leon Lieblich", + "Berufsausbildung_Funktion": "Eseltrainer", + "Beschaeftigungszeitraum": "01/99-", + "Woechentliche_Arbeitszeit": 24, + "Regelarbeitszeit": 24, + "Entgeltgruppe": "E14", + "Jahresaufwand": 134000, + "Zuschuss": 32000 + }, + { + "Lfd_Nr": 2, + "Name": "Viktoria Vergnüglich", + "Berufsausbildung_Funktion": "Eseltrainerin", + "Beschaeftigungszeitraum": "01/2023-", + "Woechentliche_Arbeitszeit": 38.5, + "Regelarbeitszeit": 38.5, + "Entgeltgruppe": "E14", + "Jahresaufwand": 123000, + "Zuschuss": 32000 + } + ] + } + } +} \ No newline at end of file diff --git a/enterprise-adapter/src/test/resources/request/jugendsozialarbeit_an_schulen-DM.json b/enterprise-adapter/src/test/resources/request/jugendsozialarbeit_an_schulen-DM.json new file mode 100644 index 0000000000000000000000000000000000000000..8d9d251181091c3279f5ca245fcd1da2c4790333 --- /dev/null +++ b/enterprise-adapter/src/test/resources/request/jugendsozialarbeit_an_schulen-DM.json @@ -0,0 +1,1279 @@ +{ + "header": { + "id": "jugendsozialarbeit_an_schulen-DM", + "modelType": "document", + "modelVersion": "26.0.0", + "locales": [ + { + "code": "de" + } + ], + "annotations": [ + { + "name": "roles", + "value": "admin" + } + ], + "modelReferences": [] + }, + "content": { + "modelInfo": { + "name": "jugendsozialarbeit_an_schulen-DM" + }, + "modelConfig": { + "decimalSeparator": ".", + "timeZone": "UTC" + }, + "modelRoot": { + "rootGroups": [ + { + "type": "Group", + "id": "group_e6cca", + "name": "root", + "Group": { + "repeatability": 1, + "required": true, + "elements": [ + { + "type": "Field", + "id": "field_89587", + "name": "Haushaltsjahr", + "Field": { + "fieldType": { + "type": "DateFragmentType", + "DateFragmentType": { + "formatOfFragment": "yyyy" + } + }, + "label": [ + { + "locale": "de", + "text": "Haushaltsjahr" + } + ] + } + }, + { + "type": "Group", + "id": "group_49b20", + "name": "Angaben_Antragssteller", + "Group": { + "repeatability": 1, + "required": true, + "elements": [ + { + "type": "Field", + "id": "field_65687", + "name": "Name_Bezeichnung", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Name/Bezeichnung" + } + ], + "required": true + } + }, + { + "type": "Field", + "id": "field_4a6d0", + "name": "Strasse_Hausnummer", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Straße, Hausnummer" + } + ] + } + }, + { + "type": "Field", + "id": "field_b2e13", + "name": "PLZ", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "errorMessage": [ + { + "locale": "de", + "text": "Bitte geben Sie eine valide Postleitzahl an." + } + ], + "pattern": "[\\d]{5}" + } + }, + "label": [ + { + "locale": "de", + "text": "PLZ" + } + ] + } + }, + { + "type": "Field", + "id": "field_a2612", + "name": "Ort", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Ort" + } + ] + } + }, + { + "type": "Field", + "id": "field_d1dc0", + "name": "Telefon", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Telefon" + } + ] + } + }, + { + "type": "Field", + "id": "field_3d3e0", + "name": "Fax", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Fax" + } + ] + } + }, + { + "type": "Field", + "id": "field_a7755", + "name": "EMail", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "E-Mail" + } + ] + } + }, + { + "type": "Field", + "id": "field_a7cef", + "name": "Verantwortlicher_Vertreter", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Verantwortliche Vertreterin/Verantwortlicher Vertreter" + } + ] + } + }, + { + "type": "Field", + "id": "field_293a6", + "name": "Zustaendiger_Sachbearbeiter", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Zuständige Sachbearbeiterin/Zuständiger Sachbearbeiter" + } + ] + } + }, + { + "type": "Group", + "id": "group_44061", + "name": "Bankverbindung", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_77875", + "name": "Kreditinstitut", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Kreditinstitut" + } + ] + } + }, + { + "type": "Field", + "id": "field_807c3", + "name": "Kontoinhaber", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Kontoinhaber" + } + ] + } + }, + { + "type": "Field", + "id": "field_fb270", + "name": "IBAN", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "errorMessage": [ + { + "locale": "de", + "text": "Bitte geben Sie eine valide IBAN an." + } + ], + "pattern": "DE\\d{2}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{2}|DE\\d{20}" + } + }, + "label": [ + { + "locale": "de", + "text": "IBAN" + } + ] + } + }, + { + "type": "Field", + "id": "field_d1499", + "name": "BIC", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "errorMessage": [ + { + "locale": "de", + "text": "Bitte geben Sie eine valide BIC an." + } + ], + "pattern": "[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}" + } + }, + "label": [ + { + "locale": "de", + "text": "BIC" + } + ] + } + } + ] + } + }, + { + "type": "Group", + "id": "group_d267e", + "name": "Zustaendiger_Spitzenverband", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_e73fd", + "name": "Bezeichnung", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Bezeichnung" + } + ] + } + }, + { + "type": "Field", + "id": "field_ca3c1", + "name": "Strasse_Hausnummer", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Straße, Hausnummer" + } + ] + } + }, + { + "type": "Field", + "id": "field_f002d", + "name": "PLZ", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "errorMessage": [ + { + "locale": "de", + "text": "Bitte geben Sie eine valide Postleitzahl an." + } + ], + "pattern": "[\\d]{5}" + } + }, + "label": [ + { + "locale": "de", + "text": "PLZ" + } + ] + } + }, + { + "type": "Field", + "id": "field_47beb", + "name": "Ort", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Ort" + } + ] + } + } + ] + } + } + ] + } + }, + { + "type": "Group", + "id": "group_66b19", + "name": "Angaben_zum_Projekt", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_de8f8", + "name": "Bezeichnung", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Bezeichnung der Maßnahme (Name der Schule)" + } + ] + } + }, + { + "type": "Field", + "id": "field_83207", + "name": "Beginn_der_Massnahme", + "Field": { + "fieldType": { + "type": "DateType", + "DateType": { + "format": "yyyy-MM-dd" + } + }, + "label": [ + { + "locale": "de", + "text": "Beginn der Maßnahme seit Genehmigung\nbzw. ggf. seit Aufstockung" + } + ] + } + }, + { + "type": "Field", + "id": "field_18de1", + "name": "Verantwortlicher_Sachbearbeiter", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Verantwortliche Sachbearbeiterin/Verantwortlicher Sachbearbeiter des Trägers der öffentl. Jugendhilfe (Landkreis/kreisfreie Stadt)" + } + ] + } + }, + { + "type": "Field", + "id": "field_dcaf0", + "name": "Strasse_Hausnummer", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Straße, Hausnummer" + } + ] + } + }, + { + "type": "Field", + "id": "field_a11e7", + "name": "PLZ", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "errorMessage": [ + { + "locale": "de", + "text": "Bitte geben Sie eine valide Postleitzahl an." + } + ], + "pattern": "[\\d]{5}" + } + }, + "label": [ + { + "locale": "de", + "text": "PLZ" + } + ] + } + }, + { + "type": "Field", + "id": "field_7afb0", + "name": "Ort", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Ort" + } + ] + } + }, + { + "type": "Field", + "id": "field_4f06a", + "name": "Telefon", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Telefon" + } + ] + } + }, + { + "type": "Field", + "id": "field_236e2", + "name": "Fax", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Fax" + } + ] + } + }, + { + "type": "Field", + "id": "field_b59d5", + "name": "EMail", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "E-Mail" + } + ] + } + } + ] + } + }, + { + "type": "Group", + "id": "group_cade6", + "name": "Anlage_1", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Group", + "id": "group_7b67f", + "name": "Personalkosten", + "Group": { + "repeatability": 10, + "elements": [ + { + "type": "Field", + "id": "field_275b9", + "name": "Lfd_Nr", + "Field": { + "fieldType": { + "type": "NumberType" + }, + "label": [ + { + "locale": "de", + "text": "Lfd. Nr." + } + ] + } + }, + { + "type": "Field", + "id": "field_2d26e", + "name": "Name", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Vor- und Zuname der Fachkraft" + } + ] + } + }, + { + "type": "Field", + "id": "field_71e95", + "name": "Berufsausbildung_Funktion", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Berufsausbildung und Funktion im geförderten Projekt (sofern noch nicht vorliegend, bitte Ausbildungsnachweis beilegen)" + } + ] + } + }, + { + "type": "Field", + "id": "field_e19d7", + "name": "Beschaeftigungszeitraum", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Beschäftigungszeitraum" + } + ] + } + }, + { + "type": "Field", + "id": "field_79cef", + "name": "Woechentliche_Arbeitszeit", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "maxFractionalDigits": 1 + } + }, + "label": [ + { + "locale": "de", + "text": "wöchentl. Arbeitszeit" + } + ] + } + }, + { + "type": "Field", + "id": "field_d1447", + "name": "Regelarbeitszeit", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "maxFractionalDigits": 1 + } + }, + "label": [ + { + "locale": "de", + "text": "tarifliche Regelarbeitszeit beim Träger" + } + ] + } + }, + { + "type": "Field", + "id": "field_ff859", + "name": "Entgeltgruppe", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Entgeltgruppe" + } + ] + } + }, + { + "type": "Field", + "id": "field_f618b", + "name": "Jahresaufwand", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Jahresaufwand in €" + } + ] + } + }, + { + "type": "Field", + "id": "field_f994b", + "name": "Zuschuss", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Zuschuss Festbetragsförderung (nicht vom Antragsteller auszufüllen)" + } + ] + } + } + ] + } + } + ] + } + }, + { + "type": "Group", + "id": "group_d7cfe", + "name": "Anlage_2", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Group", + "id": "group_55285", + "name": "Kostenplan", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_98416", + "name": "Personalkosten_JaS", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Personalkosten der JaS-Fachkraft/Fachkräfte" + } + ] + } + }, + { + "type": "Field", + "id": "field_ebdd5", + "name": "Personalkosten_Sonstige", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Sonstige Personalkosten" + } + ] + } + }, + { + "type": "Field", + "id": "field_20288", + "name": "Sachkosten", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Sachkosten für den lfd. Betrieb" + } + ] + } + }, + { + "type": "Field", + "id": "field_b7bb2", + "name": "Sonstige_Kosten", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Sonstige Kosten" + } + ] + } + }, + { + "type": "Field", + "id": "field_e4001", + "name": "Insgesamt_Kostenplan", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Insgesamt" + } + ] + } + }, + { + "type": "Computation", + "id": "computation_2098f", + "name": "Insgesamt_Kostenplan_Comp", + "Computation": { + "computedFieldId": "field_e4001", + "computationAlternatives": [ + { + "operation": "[Personalkosten_Sonstige]+[Personalkosten_JaS]+[Sachkosten]+[Sonstige_Kosten]" + } + ], + "errorMessage": [ + { + "locale": "de", + "text": "error text for computation of Insgesamt_Kostenplan_Comp" + } + ] + } + }, + { + "type": "Field", + "id": "field_d09ae", + "name": "Erlaeuterungen_Kostenplan", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "lineBreaksPermitted": true + } + }, + "label": [ + { + "locale": "de", + "text": "Erläuterungen" + } + ] + } + } + ] + } + }, + { + "type": "Group", + "id": "group_60c8d", + "name": "Finanzierungsplan", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_7e8f3", + "name": "Eigenmittel_von_Hundert", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "percent" + } + }, + "label": [ + { + "locale": "de", + "text": "Eigenmittel von Hundert" + } + ] + } + }, + { + "type": "Field", + "id": "field_228aa", + "name": "Eigenmittel_Betrag", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Eigenmittel Betrag" + } + ] + } + }, + { + "type": "Field", + "id": "field_264d6", + "name": "Zuwendungen_kirchlicher_Stellen", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Zuwendungen kirchlicher Stellen" + } + ] + } + }, + { + "type": "Field", + "id": "field_55d96", + "name": "Angabe_der_kirchlichen_Stelle", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Angabe der Stelle" + } + ] + } + }, + { + "type": "Group", + "id": "group_cb4bd", + "name": "Zuwendung_kommunale", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_516a4", + "name": "Gemeinden", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Gemeinden" + } + ] + } + }, + { + "type": "Field", + "id": "field_d53ed", + "name": "Zuwendung_Gemeinden", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Betrag" + } + ] + } + }, + { + "type": "Field", + "id": "field_3216a", + "name": "Landkreise", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Landkreise" + } + ] + } + }, + { + "type": "Field", + "id": "field_830de", + "name": "Zuwendung_Landkreise", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Betrag" + } + ] + } + } + ] + } + }, + { + "type": "Field", + "id": "field_45f01", + "name": "Zuwendungen_Bezirk", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Zuwendungen des Bezirks" + } + ] + } + }, + { + "type": "Group", + "id": "group_dbe9b", + "name": "Sonstige_oeffentliche_Mittel", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_fe71d", + "name": "Angabe_Bewilligungstelle_sonsitge_oeffentl_Mittel", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Angabe der Bewilligungsstelle" + } + ] + } + }, + { + "type": "Field", + "id": "field_1c494", + "name": "Betrag_sonsitge_oeffentl_Mittel", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Betrag" + } + ] + } + } + ] + } + }, + { + "type": "Group", + "id": "group_4ec36", + "name": "Fremdmittel", + "Group": { + "repeatability": 1, + "elements": [ + { + "type": "Field", + "id": "field_68026", + "name": "Angabe_Bewilligungstelle_Fremdmittel", + "Field": { + "fieldType": { + "type": "StringType" + }, + "label": [ + { + "locale": "de", + "text": "Angabe der Bewilligungsstelle" + } + ] + } + }, + { + "type": "Field", + "id": "field_e59dd", + "name": "Betrag_Fremdmittel", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Betrag" + } + ] + } + } + ] + } + }, + { + "type": "Field", + "id": "field_81843", + "name": "Beantragter_Zuschuss", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Beantragter Zuschuss des Bayerischen Staatsministeriums für Familie, Arbeit und Soziales" + } + ] + } + }, + { + "type": "Field", + "id": "field_479e3", + "name": "Insgesamt_Finanzierungsplan", + "Field": { + "fieldType": { + "type": "NumberType", + "NumberType": { + "minFractionalDigits": 2, + "maxFractionalDigits": 2, + "trait": "amount" + } + }, + "label": [ + { + "locale": "de", + "text": "Insgesamt" + } + ] + } + }, + { + "type": "Computation", + "id": "computation_3849f", + "name": "Insgesamt_Kostenplan_Comp", + "Computation": { + "computedFieldId": "field_479e3", + "computationAlternatives": [ + { + "operation": "[Eigenmittel_Betrag]+[Zuwendungen_kirchlicher_Stellen]+[Zuwendung_kommunale/Zuwendung_Gemeinden]+[Zuwendung_kommunale/Zuwendung_Landkreise]+[Sonstige_oeffentliche_Mittel/Betrag_sonsitge_oeffentl_Mittel]+[Fremdmittel/Betrag_Fremdmittel]+[Beantragter_Zuschuss]" + } + ], + "errorMessage": [ + { + "locale": "de", + "text": "error text for computation of Insgesamt_Kostenplan_Comp" + } + ] + } + }, + { + "type": "Field", + "id": "field_b1b30", + "name": "Erlaeuterungen_Finanzierungsplan", + "Field": { + "fieldType": { + "type": "StringType", + "StringType": { + "lineBreaksPermitted": true + } + }, + "label": [ + { + "locale": "de", + "text": "Erläuterungen" + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } +} \ No newline at end of file diff --git a/formcycle-adapter/formcycle-adapter-impl/pom.xml b/formcycle-adapter/formcycle-adapter-impl/pom.xml index 3cb1d3fb8eddd78716f644d0265b8c7aafa702c2..ed03ed830eec84d901e4204ac5744348f38ce11b 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapper.java b/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapper.java index 40b324dbdd4cdb25229e037a426cb8f19dd9fd07..8db87c762e8ec704b791b8744f3182f2fcd63a8e 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapper.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapper.java @@ -43,5 +43,6 @@ public interface FormCycleFormDataMapper { @Mapping(target = "zustaendigeStelle.organisationseinheitenId", source = "header.organisationsEinheitId") @Mapping(target = "header.formEngineName", constant = "FormCycle") @Mapping(target = "header.createdAt", source = "header.receivedAt") + @Mapping(target = "header.requestId", source = "header.requestId", defaultExpression = "java(java.util.UUID.randomUUID().toString())") FormData toFormData(FormCycleFormData fcFormData); } diff --git a/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormDataController.java b/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormDataController.java index 06206c9f99a6bc1d9442c5452979f90090faa60a..4e6fbc510208c4bc5154d7b6e98327c938cc2af4 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormDataController.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/main/java/de/ozgcloud/eingang/formcycle/FormDataController.java @@ -81,11 +81,11 @@ class FormDataController { semantikAdapter.processFormData(mappedFormData); - return FormCycleConfirmationResponse.newBuilder().setVorgangNummer(mappedFormData.getHeader().getRequestId()).build(); + return FormCycleConfirmationResponse.newBuilder().setVorgangNummer(mappedFormData.getHeader().getVorgangNummer()).build(); } private FormData addVorgangNummer(FormData mappedFormData) { - var formDataHeader = mappedFormData.getHeader().toBuilder().requestId(vorgangNummerSupplier.get()).build(); + var formDataHeader = mappedFormData.getHeader().toBuilder().vorgangNummer(vorgangNummerSupplier.get()).build(); return mappedFormData.toBuilder().header(formDataHeader).build(); } diff --git a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapperTest.java b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapperTest.java index e12156bc8c9ca0f7194f5f8134bc070669d73e04..feb214cccd2dca6533c39109f6f85619be567304 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapperTest.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormDataMapperTest.java @@ -31,6 +31,7 @@ import org.mapstruct.factory.Mappers; import org.mockito.InjectMocks; import org.mockito.Spy; +import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper; class FormCycleFormDataMapperTest { @@ -46,9 +47,12 @@ class FormCycleFormDataMapperTest { @Test void shouldMapHeader() { + var expectedFormHeader = FormHeaderTestFactory.create(); + var mapped = mapper.toFormData(FormCycleFormDataTestFactory.create()); - assertThat(mapped.getHeader()).isNotNull(); + assertThat(mapped.getHeader()).usingRecursiveComparison() + .ignoringFields("vorgangNummer", "sender", "formEngineName", "serviceKonto").isEqualTo(expectedFormHeader); } @Test diff --git a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormHeaderTestFactory.java b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormHeaderTestFactory.java index 04a0737a8b81102864d16dfca6c6ee1e7910d9ca..3065efa67f043925acf7204557ede13253660b10 100644 --- a/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormHeaderTestFactory.java +++ b/formcycle-adapter/formcycle-adapter-impl/src/test/java/de/ozgcloud/eingang/formcycle/FormCycleFormHeaderTestFactory.java @@ -23,12 +23,12 @@ */ package de.ozgcloud.eingang.formcycle; +import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; import de.ozgcloud.eingang.formcycle.FormCycleFormHeader.Builder; public class FormCycleFormHeaderTestFactory { - static final String RECEIVED_AT = "2022-12-24T18:00:00Z"; - static final String FORM_NAME = "test form 1"; + static final String RECEIVED_AT = FormHeaderTestFactory.CREATED_AT_STR; static final String ORGANISATIONSEINHEIT_ID = "9030229"; static FormCycleFormHeader create() { @@ -37,8 +37,10 @@ public class FormCycleFormHeaderTestFactory { static Builder createBuilder() { return FormCycleFormHeader.newBuilder() - .setFormName(FORM_NAME) + .setRequestId(FormHeaderTestFactory.REQUEST_ID) + .setFormName(FormHeaderTestFactory.FORM_NAME) .setReceivedAt(RECEIVED_AT) + .setFormId(FormHeaderTestFactory.FORM_ID) .setOrganisationsEinheitId(ORGANISATIONSEINHEIT_ID); } } 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 25a588403ce89dc7c6bfa1cd89a5972f0ef2a458..06704947aea190ae8c3ee084a492c3b6d808e479 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 @@ -51,6 +51,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.FormHeader; +import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress; @@ -87,8 +88,6 @@ class FormDataControllerTest { @Nested class ReceiveFormData { - static final String VORGANG_NUMMER = "VorgangNummer"; - private FormData mappedFormData = FormDataTestFactory.create(); @Captor @@ -98,7 +97,7 @@ class FormDataControllerTest { void init() { when(htmlCleaner.clean(any())).thenReturn(mappedFormData); when(mapper.toFormData(any())).thenReturn(mappedFormData); - when(vorgangNummerSupplier.get()).thenReturn(VORGANG_NUMMER); + when(vorgangNummerSupplier.get()).thenReturn(FormHeaderTestFactory.VORGANG_NUMMER); } @Test @@ -120,7 +119,7 @@ class FormDataControllerTest { var confirmation = FormCycleConfirmationResponse.parseFrom( doPostRequest().andReturn().getResponse().getContentAsByteArray()); - assertThat(confirmation.getVorgangNummer()).isEqualTo(VORGANG_NUMMER); + assertThat(confirmation.getVorgangNummer()).isEqualTo(FormHeaderTestFactory.VORGANG_NUMMER); } @Test @@ -128,7 +127,7 @@ class FormDataControllerTest { doPostRequest(); verify(semantikAdapter).processFormData(formDataCaptor.capture()); - assertThat(formDataCaptor.getValue().getHeader().getRequestId()).isEqualTo(VORGANG_NUMMER); + assertThat(formDataCaptor.getValue().getHeader().getRequestId()).isEqualTo(FormHeaderTestFactory.REQUEST_ID); } @Test @@ -151,7 +150,7 @@ class FormDataControllerTest { verify(semantikAdapter).processFormData(formDataCaptor.capture()); assertThat(formDataCaptor.getValue()).usingRecursiveComparison() - .ignoringFields("representations", "attachments", "numberOfAttachments", "header.requestId") + .ignoringFields("representations", "attachments", "numberOfAttachments") .isEqualTo(mappedFormData); } diff --git a/formcycle-adapter/formcycle-adapter-interface/pom.xml b/formcycle-adapter/formcycle-adapter-interface/pom.xml index 21e5e3f512c753f7c576cb894854388968816595..5951e22341367d1318a44e630d0b6baf4035d8f7 100644 --- a/formcycle-adapter/formcycle-adapter-interface/pom.xml +++ b/formcycle-adapter/formcycle-adapter-interface/pom.xml @@ -29,14 +29,14 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-dependencies</artifactId> - <version>4.0.1</version> + <version>4.2.0</version> <relativePath/> </parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>formcycle-adapter-interface</artifactId> <name>EM - Formcycle Adapter - Interface</name> - <version>2.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <properties> <vorgang-manager.version>2.0.0</vorgang-manager.version> diff --git a/formcycle-adapter/formcycle-adapter-interface/src/main/protobuf/form-data.model.proto b/formcycle-adapter/formcycle-adapter-interface/src/main/protobuf/form-data.model.proto index ccac014c15c44f208360b6c4dc8c0d23d4e77504..28ff49ebad2b3dba76a536a6df872d2f43ed210e 100644 --- a/formcycle-adapter/formcycle-adapter-interface/src/main/protobuf/form-data.model.proto +++ b/formcycle-adapter/formcycle-adapter-interface/src/main/protobuf/form-data.model.proto @@ -47,6 +47,8 @@ message FormCycleFormHeader { string receivedAt = 1; string formName = 2; string organisationsEinheitId = 3; + string formId = 4; + string requestId = 5; } message FormCycleServiceKonto { diff --git a/formcycle-adapter/pom.xml b/formcycle-adapter/pom.xml index 16b6c8e4d98f2a859eaa3f0ab25d29e59a95b844..63b93d221b06b16291daed58ab4fe63eaa69d2cc 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> </parent> <artifactId>formcycle-adapter</artifactId> diff --git a/formsolutions-adapter/pom.xml b/formsolutions-adapter/pom.xml index 952b50c715b0346251c2ed9f00ca0e60b4c1e86e..03eb9a613234b0185ad0dc5baa5845924afa19c6 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/forwarder/pom.xml b/forwarder/pom.xml index a58d20065792d755199352bb724e9d5032a93666..e42078568cc69cd957b06d28469984bf9a4ddec4 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/intelliform-adapter/pom.xml b/intelliform-adapter/pom.xml index 6a9627f80baf281236d2b09bb60f18056d3c82e4..c5a62fb727d1b2d2c5874064eb54ade65443a994 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/SemantikAdapterConfiguration.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/SemantikAdapterConfiguration.java deleted file mode 100644 index 7c70b8144a3b5da22da7b1962216c9ada61dceba..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/SemantikAdapterConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2022 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; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedAdapter; - -@Configuration -public class SemantikAdapterConfiguration { - - @Bean - public EngineBasedSemantikAdapter engineBasedSemantikAdapter() { - return new AfmEngineBasedAdapter(); - } - -} \ No newline at end of file diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdder.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdder.java deleted file mode 100644 index 9bf4387c8ed466c54cf64b09d9f800e7346b0d9f..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdder.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.stereotype.Component; - -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; - -@Component -public class AttachmentsContentAdder { - - public List<IncomingFileGroup> addContentToAttachments(List<IncomingFileGroup> formDataFileGroups, List<IncomingFile> depositRequestFiles) { - var fileGroups = new ArrayList<IncomingFileGroup>(formDataFileGroups.size()); - for (IncomingFileGroup fileGroup : formDataFileGroups) { - var files = fileGroup.getFiles().stream() - .map(file -> file.toBuilder().file(getContentStreamFromDepositRequest(file.getVendorId(), depositRequestFiles)).build()) - .toList(); - fileGroups.add(fileGroup.toBuilder().clearFiles().files(files).build()); - } - return Collections.unmodifiableList(fileGroups); - } - - private File getContentStreamFromDepositRequest(String attachmentVendorId, List<IncomingFile> depositRequestFiles) { - - return depositRequestFiles.stream() - .filter(depositFile -> depositFile.getVendorId().equals(attachmentVendorId)) - .map(IncomingFile::getFile) - .findFirst() - .orElseThrow(() -> new RuntimeException( - "DepositFiles does not contain content for attachment with vendorId: " + attachmentVendorId)); - } -} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/CustomHeaderReader.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/CustomHeaderReader.java deleted file mode 100644 index dad25e9f009aa064cc79e5837ccf4687d0dcdc89..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/CustomHeaderReader.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.function.Consumer; - -import org.springframework.stereotype.Component; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; - -@Component -public class CustomHeaderReader { - - public static final String HEADER_POSTFACH_ID = "u:saml_legacypostkorbhandle"; - public static final String HEADER_VORNAME = "u:saml_givenname"; - public static final String HEADER_NACHNAME = "u:saml_surname"; - public static final String HEADER_GEBURTSORT = "u:saml_placeofbirth"; - public static final String HEADER_GEBURTSNAME = "u:saml_birthname"; - public static final String HEADER_EMAIL = "u:saml_mail"; - public static final String HEADER_TELEFON = "u:saml_telephonenumber"; - public static final String HEADER_STRASSE = "u:saml_postaladdress"; - public static final String HEADER_PLZ = "u:saml_postalcode"; - public static final String HEADER_ORT = "u:saml_localityname"; - - public Map<String, Object> getHeader(Document document) { - var map = new HashMap<String, Object>(); - Consumer<Attr> addHeader = attr -> map.put(attr.getName(), attr.getValue()); - getAttribute(document, HEADER_POSTFACH_ID).ifPresent(addHeader); - getAttribute(document, HEADER_VORNAME).ifPresent(addHeader); - getAttribute(document, HEADER_NACHNAME).ifPresent(addHeader); - getAttribute(document, HEADER_GEBURTSNAME).ifPresent(addHeader); - getAttribute(document, HEADER_GEBURTSORT).ifPresent(addHeader); - getAttribute(document, HEADER_EMAIL).ifPresent(addHeader); - getAttribute(document, HEADER_TELEFON).ifPresent(addHeader); - getAttribute(document, HEADER_STRASSE).ifPresent(addHeader); - getAttribute(document, HEADER_PLZ).ifPresent(addHeader); - getAttribute(document, HEADER_ORT).ifPresent(addHeader); - return map; - } - - Optional<Attr> getAttribute(Document document, String name) { - return Optional.ofNullable(document.getDocumentElement().getAttributeNode(name)); - } -} \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..b12dfc7a99548a5868891da6608dab10242e64d2 --- /dev/null +++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2022 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.intelliform; + +import static java.util.stream.Collectors.*; + +import java.io.IOException; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.springframework.stereotype.Component; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import de.ozgcloud.common.binaryfile.TempFileUtils; +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +class DepositDataMapper { + + // TODO Resolve code duplication (xta-adapter: de.ozgcloud.eingang.xdomea.XMLHelper) + private static final DocumentBuilder DOCUMENT_BUILDER = createDocumentBuilder(); + + private static DocumentBuilder createDocumentBuilder() { + var documentBuilderFactory = DocumentBuilderFactory.newInstance(); + try { + documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + return documentBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new TechnicalException("Failed to configure document builder", e); + } + } + + public FormData mapToFormData(DepositData depositData) { + Map<String, IncomingFile> incomingFileMap = mapDepositAttachmentsToIncomingFiles(depositData); + Document document = parsePrimaryXmlRepresentation(depositData, incomingFileMap); + var attachmentGroups = findAttachmentGroups(document); + + return mapToFormDataWithRepresentationsAndAttachments( + getRepresentations(incomingFileMap, getAttachmentFileIds(attachmentGroups)), + getAttachmentFileGroups(attachmentGroups, incomingFileMap) + ); + } + + private List<String> getAttachmentFileIds(Map<String, List<String>> attachmentGroups) { + return attachmentGroups.values().stream() + .flatMap(Collection::stream) + .toList(); + } + + private FormData mapToFormDataWithRepresentationsAndAttachments( + List<IncomingFile> representations, + List<IncomingFileGroup> attachments + ) { + return FormData.builder() + .attachments(attachments) + .numberOfAttachments(attachments.size()) + .representations(representations) + .numberOfRepresentations(representations.size()) + .build(); + } + + Map<String, IncomingFile> mapDepositAttachmentsToIncomingFiles(DepositData depositData) { + return depositData.getAttachments() + .stream() + .collect(Collectors.toMap( + Attachment::getId, + this::mapAttachmentToIncomingFile, + (u, v) -> v, + LinkedHashMap::new)); + } + + IncomingFile mapAttachmentToIncomingFile(Attachment attachment) { + var file = TempFileUtils.writeTmpFile(attachment.content); + return IncomingFile.builder() + .id(UUID.randomUUID().toString()) + .vendorId(attachment.id) + .name(attachment.name) + .contentType(attachment.contentType) + .size(file.length()) + .file(file) + .build(); + } + + private Document parsePrimaryXmlRepresentation(DepositData depositData, Map<String, IncomingFile> incomingFileMap) { + // Expect that the <primaryDataAttachmentId> refers to the XML file + return parseDocument( + getIncomingFileById(depositData.getPrimaryDataAttachmentId(), incomingFileMap) + ); + } + + private static Document parseDocument(IncomingFile incomingFile) { + try (var inputStream = incomingFile.getContentStream()) { + return DOCUMENT_BUILDER.parse(inputStream); + } catch (SAXException | IOException e) { + throw new TechnicalException("Failed to parse xml document!", e); + } + } + + Map<String, List<String>> findAttachmentGroups(Document document) { + return streamElements(document.getElementsByTagName("file")) + .collect(groupingBy( + element -> element.getParentNode().getNodeName(), + mapping( + element -> element.getAttribute("id"), + toList()))); + } + + private List<IncomingFileGroup> getAttachmentFileGroups(Map<String, List<String>> attachmentGroups, Map<String, IncomingFile> incomingFileMap) { + return attachmentGroups.entrySet().stream() + .map(entry -> IncomingFileGroup.builder() + .name(entry.getKey()) + .files(entry.getValue().stream().map(id -> getIncomingFileById(id, incomingFileMap)).toList()) + .build()) + .toList(); + } + + private List<IncomingFile> getRepresentations(Map<String, IncomingFile> incomingFileMap, List<String> attachmentFileIds) { + return getNamesWithout(incomingFileMap.keySet(), attachmentFileIds).stream() + .map(id -> getIncomingFileById(id, incomingFileMap)) + .toList(); + } + + private IncomingFile getIncomingFileById(String id, Map<String, IncomingFile> incomingFileMap) { + if (!incomingFileMap.containsKey(id)) { + throw new TechnicalException("Failed to find <file> attachment ID '%s' in deposit data!".formatted(id)); + } + return incomingFileMap.get(id); + } + + private List<String> getNamesWithout(Collection<String> names, Collection<String> excludedStrings) { + var excludedStringsSet = Set.copyOf(excludedStrings); + return names.stream().filter(name -> !excludedStringsSet.contains(name)).toList(); + } + + private Stream<Element> streamElements(NodeList nodeList) { + return IntStream.range(0, nodeList.getLength()) + .mapToObj(nodeList::item) + .map(Element.class::cast); + } + +} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapper.java deleted file mode 100644 index db6bc571cea5ba0c9897dfef2bd7ded128ca9c35..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapper.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.util.List; -import java.util.UUID; - -import org.springframework.stereotype.Component; - -import de.ozgcloud.common.binaryfile.TempFileUtils; -import de.ozgcloud.eingang.common.formdata.IncomingFile; - -@Component -class DepositRequestIncomingFileMapper { - - List<IncomingFile> mapFiles(Deposit depositData) { - return depositData.getData().getAttachments().stream() - .map(this::buildIncomingFile).toList(); - } - - private IncomingFile buildIncomingFile(Attachment attachment) { - var file = TempFileUtils.writeTmpFile(attachment.content); - - return IncomingFile.builder() - .id(UUID.randomUUID().toString()) - .vendorId(attachment.getId()) - .name(attachment.getName()) - .file(file) - .contentType(attachment.getContentType()) - .size(attachment.getContent().length) - .build(); - } -} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java index 85fba9a36193a7303b83c4dce077ed65dac682e7..76738410397858f63368580eef3fe9e274cfc930 100644 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java +++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java @@ -43,24 +43,27 @@ import lombok.extern.log4j.Log4j2; @Log4j2 public class FormDataEndpoint { - private static final String NAMESPACE_URI = "http://xmlns.cit.de/intelliform/2009/webservices/backend"; + static final String NAMESPACE_URI = "http://xmlns.cit.de/intelliform/2009/webservices/backend"; + static final String PAYLOAD_LOCAL_PART = "deposit"; private static final ObjectFactory objectFactory = new ObjectFactory(); private static final QName _DepositResponse_QNAME = new QName(NAMESPACE_URI, "depositResponse"); private static final QName _PrefillResponse_QNAME = new QName(NAMESPACE_URI, "prefillResponse"); + @Autowired - private SemantikFormDataMapper semantikFormDataMapper; + private DepositDataMapper depositDataMapper; @Autowired private SemantikAdapter semantikAdapter; - @PayloadRoot(namespace = NAMESPACE_URI, localPart = "deposit") + @PayloadRoot(namespace = NAMESPACE_URI, localPart = PAYLOAD_LOCAL_PART) @ResponsePayload public JAXBElement<DepositResponse> inputFormData(@RequestPayload Deposit deposit) throws IOException, ParserConfigurationException { try { - semantikAdapter.processFormData(semantikFormDataMapper.mapToFormData(deposit)); + var formData = depositDataMapper.mapToFormData(deposit.getData()); + semantikAdapter.processFormData(formData); } catch (Exception e) { LOG.error("Error processing form data", e); throw e; diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapper.java deleted file mode 100644 index 6cd2ec7ceadb5a02f19ce3560858d3cb224d26eb..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapper.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.springframework.stereotype.Component; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; - -@Component -class FormDataIncomingFileMapper { - - int countAttachments(Document document) { - return document.getElementsByTagName("file").getLength(); - } - - List<IncomingFileGroup> mapAttachments(Document document) { - List<IncomingFileGroup> incomingFileGroups = new ArrayList<>(); - NodeList files = document.getElementsByTagName("file"); - - for (int idx = 0; idx < files.getLength(); idx++) { - String parentNodeName = buildParentNodeName(files.item(idx).getParentNode().getNodeName()); - IncomingFileGroup group = getIncomingFileGroup(incomingFileGroups, parentNodeName); - var updatedGroup = group.toBuilder().file(mapNodeToIncomingFile(files.item(idx))).build(); - incomingFileGroups.remove(group); - incomingFileGroups.add(updatedGroup); - } - - return incomingFileGroups; - } - - String buildParentNodeName(String parentNodeName) { - return parentNodeName.replaceAll("-item$", ""); - } - - private IncomingFile mapNodeToIncomingFile(Node item) { - return IncomingFile.builder() - .id(UUID.randomUUID().toString()) - .vendorId(item.getAttributes().getNamedItem("id").getNodeValue()) - .name(item.getFirstChild().getTextContent()) - .contentType(item.getAttributes().getNamedItem("content-type").getNodeValue()) - .size(Integer.valueOf(item.getAttributes().getNamedItem("length").getNodeValue())) - .build(); - } - - private IncomingFileGroup getIncomingFileGroup(List<IncomingFileGroup> incomingFileGroups, String parentNodeName) { - return incomingFileGroups.stream() - .filter(group -> group.getName().equals(parentNodeName)) - .findFirst() - .orElseGet(() -> { - IncomingFileGroup fileGroup = IncomingFileGroup.builder().name(parentNodeName).build(); - incomingFileGroups.add(fileGroup); - return fileGroup; - }); - } -} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculator.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculator.java deleted file mode 100644 index 9018f33263566ab69c239614ca9d6f07aec81afc..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.util.List; -import java.util.stream.Collectors; - -import org.springframework.stereotype.Component; - -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; - -@Component -public class RepresentationsCalculator { - - List<IncomingFile> calculateRepresentations(List<IncomingFileGroup> formDataFileGroups, List<IncomingFile> depositRequestFiles) { - - return depositRequestFiles.stream() - .filter(file -> !formDataContainsFile(formDataFileGroups, file)) - .collect(Collectors.toList()); - } - - private boolean formDataContainsFile(List<IncomingFileGroup> formDataFileGroups, IncomingFile depositDataFile) { - - return formDataFileGroups.stream() - .anyMatch(fileGroup -> fileGroup.getFiles().stream() - .anyMatch(file -> file.getVendorId().equals(depositDataFile.getVendorId()))); - } -} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapper.java deleted file mode 100644 index f4796328f0f9469c17291a9f4dfda6655c1213cf..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapper.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.io.ByteArrayInputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.w3c.dom.Document; - -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; -import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper; -import lombok.RequiredArgsConstructor; - -//TODO Naming prüfen - er scheint mir nicht semantik zu mappen und befindet sich auch nicht im entsprechenden Modul -@Component -@RequiredArgsConstructor -class SemantikFormDataMapper { - static final String FILE = "file"; - - static final String CONTENT_FORMDATA_FILENAME_SUFFIX = "-Daten.xml"; - - static final String ATTACHMENTS_FIELD = "depositAttachments"; - - static final String ATTACHMENT_ID = "id"; - static final String ATTACHMENT_NAME = "name"; - static final String ATTACHMENT_DESCRIPTION = "description"; - static final String ATTACHMENT_ATTRIBUTES = "attributes"; - static final String ATTACHMENT_CONTENT = "content"; - static final String ATTACHMENT_CONTENT_TYPE = "contentType"; - - static final String HEADER_FIELD = "header"; - - static final String HEADER_ID = "t:id"; - static final String HEADER_TIMESTAMP = "t:timestamp"; - static final String HEADER_FORM_ID = "t:form-id"; - static final String HEADER_FORM = "t:form"; - static final String HEADER_SENDER = "t:sender"; - static final String HEADER_CUSTOMER = "t:customer"; - static final String HEADER_CUSTOMER_ID = "t:customer-id"; - static final String HEADER_CLIENT = "t:client"; - static final String HEADER_CLIENT_ID = "t:client-id"; - - @Autowired - private final XmlToJavaMapsMapper xmlToJavaMapsMapper; - - @Autowired - private final FormDataIncomingFileMapper formDataIncomingFileMapper; - - @Autowired - private final RepresentationsCalculator incomingFilesService; - - @Autowired - private final DepositRequestIncomingFileMapper depositRequestFilesMapper; - - @Autowired - private final AttachmentsContentAdder attachmentsContentAdder; - - @Autowired - private final CustomHeaderReader customHeaderReader; - - public FormData mapToFormData(Deposit depositData) { - var xmlFormDataStream = getXmlFormData(depositData.getData()); - - var document = xmlToJavaMapsMapper.parseAsW3cDocument(new ByteArrayInputStream(xmlFormDataStream)); - var formDataMap = xmlToJavaMapsMapper.mapXmlToJavaMaps(document); - - addFiles(document, depositRequestFilesMapper.mapFiles(depositData), formDataMap); - - addHeader(document, formDataMap); - - return FormData.builder().formData(Collections.unmodifiableMap(formDataMap)).build(); - } - - private byte[] getXmlFormData(DepositData depositData) { - var primaryId = depositData.getPrimaryDataAttachmentId(); - - return depositData.getAttachments().stream() - .filter(attachment -> StringUtils.equals(attachment.getId(), primaryId)) - .map(Attachment::getContent) - .findFirst() - .orElseThrow(() -> new RuntimeException("Request does not contain primary data attachment")); - } - - private void addFiles(Document document, List<IncomingFile> depositRequestFiles, Map<String, Object> formDataMap) { - List<IncomingFileGroup> attachments = formDataIncomingFileMapper.mapAttachments(document); - attachments = attachmentsContentAdder.addContentToAttachments(attachments, depositRequestFiles); - - List<IncomingFile> representations = incomingFilesService.calculateRepresentations(attachments, depositRequestFiles); - - formDataMap.put(FilesMapperHelper.FIELD_NAME_MAPPED_FILES, Map.of( - FilesMapperHelper.ATTACHMENTS, attachments, - FilesMapperHelper.REPRESENTATIONS, representations)); - - removeMappedFileReferences(attachments, formDataMap); - } - - void removeMappedFileReferences(List<IncomingFileGroup> attachments, Map<String, Object> formDataMap) { - attachments.forEach(group -> group.getFiles().stream().map(inFile -> getReferenceName(inFile.getVendorId(), formDataMap)).toList().stream() - .forEach(ref -> ref.ifPresent(entry -> formDataMap.remove(entry.getKey())))); - } - - @SuppressWarnings("unchecked") - Optional<Map.Entry<String, Object>> getReferenceName(String vendorId, Map<String, Object> formDataMap) { - return formDataMap.entrySet().stream().filter(entry -> { - Object file = null; - - if (entry.getValue() instanceof Map) { - file = ((Map<String, Object>) entry.getValue()).get(FILE); - } - - return Objects.nonNull(file) && ((Map<String, String>) file).containsValue(vendorId); - - }).findFirst(); - } - - private void addHeader(Document document, Map<String, Object> formData) { - formData.put(HEADER_FIELD, createHeaderMap(document)); - } - - private Map<String, Object> createHeaderMap(Document document) { - var map = new HashMap<String, Object>(); - map.put(HEADER_ID, document.getDocumentElement().getAttribute(HEADER_ID)); - map.put(HEADER_TIMESTAMP, document.getDocumentElement().getAttribute(HEADER_TIMESTAMP)); - map.put(HEADER_FORM_ID, document.getDocumentElement().getAttribute(HEADER_FORM_ID)); - map.put(HEADER_FORM, document.getDocumentElement().getAttribute(HEADER_FORM)); - map.put(HEADER_SENDER, document.getDocumentElement().getAttribute(HEADER_SENDER)); - map.put(HEADER_CUSTOMER, document.getDocumentElement().getAttribute(HEADER_CUSTOMER)); - map.put(HEADER_CUSTOMER_ID, document.getDocumentElement().getAttribute(HEADER_CUSTOMER_ID)); - map.put(HEADER_CLIENT, document.getDocumentElement().getAttribute(HEADER_CLIENT)); - map.put(HEADER_CLIENT_ID, document.getDocumentElement().getAttribute(HEADER_CLIENT_ID)); - map.putAll(customHeaderReader.getHeader(document)); - return map; - } -} \ No newline at end of file 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 36b48dced9adf7c3c8c3189870f241870a44bdbf..0bc63fd67c648f3a51d7a57942cd5414a3293262 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 @@ -23,6 +23,15 @@ */ package de.ozgcloud.eingang.intelliform; +import static java.util.stream.Collectors.*; + +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import lombok.Builder; + public class AttachmentTestFactory { public static final String XML_FILE_NAME = "XML-Daten-1.xml"; @@ -38,36 +47,80 @@ public class AttachmentTestFactory { t:form-id="waffen/kleinerWaffenschein" t:customer="Einheitlicher Ansprechpartner" t:customer-id="ea-sh" t:client="Schleswig-Holstein" - t:client-id="land"></myForm>"""; - public static final byte[] XML_CONTENT = XML_CONTENT_STRING.getBytes(); - public static final String XML_ID = "myForm-xml"; + t:client-id="land"> + <Upload1> + <file content-type="image/png" description="" id="VendorId3333" length="155251">Image.png</file> + </Upload1> + </myForm>"""; + public static final String XML_CONTENT = XML_CONTENT_STRING; + public static final String XML_ATTACHMENT_ID = "myForm-xml"; public static final String XML_NAME = "XML-Daten.xml"; public static final String PDF_ATTACHMENT_CONTENT_TYPE = "application/pdf"; - public static final byte[] PDF_ATTACHMENT_CONTENT = "TestContent2".getBytes(); + public static final String PDF_ATTACHMENT_CONTENT = "TestContent2"; public static final String PDF_ATTACHMENT_NAME = "Scan1.pdf"; public static final String PDF_ATTACHMENT_ID = "VendorId2222"; + public static final String PDF2_ATTACHMENT_ID = "VendorIdpdf2"; + + public static final String PNG_ATTACHMENT_CONTENT_TYPE = "application/pdf"; + public static final String PNG_ATTACHMENT_CONTENT = "TestContent3"; + public static final String PNG_ATTACHMENT_NAME = "Image.png"; + public static final String PNG_ATTACHMENT_ID = "VendorId3333"; + + public static final String JPG_ATTACHMENT_ID = "VendorIdjpg1"; + public static final String ODT_ATTACHMENT_ID = "VendorIdodt1"; + + public static final String ODT_ATTACHMENT_CONTENT_TYPE = "application/vnd.oasis.opendocument.text"; + + public static final String DOCX_ATTACHMENT_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + public static final String DOCX_ATTACHMENT_CONTENT = "TestContent4"; + + public static final String DOCX1_ATTACHMENT_ID = "VendorIddocx1"; + public static final String DOCX2_ATTACHMENT_ID = "VendorIddocx2"; + public static final String DOCX3_ATTACHMENT_ID = "VendorIddocx3"; + public static final String DOCX4_ATTACHMENT_ID = "VendorIddocx4"; + public static final String DOCX5_ATTACHMENT_ID = "VendorIddocx5"; + public static final String DOCX6_ATTACHMENT_ID = "VendorIddocx6"; + public static final String DOCX7_ATTACHMENT_ID = "VendorIddocx7"; + public static final String DOCX8_ATTACHMENT_ID = "VendorIddocx8"; + public static final String ORGANISATIONSEINHEITEN_ID = "10363455"; + + public static final String ANTRAGSTELLER_ANREDE = "Herr"; + public static final String ANTRAGSTELLER_ANREDE_CODE = "03"; + public static final String ANTRAGSTELLER_NACHNAME = "Mustermann"; public static final String ATTRIBUTES_ENTRY_KEY = "X-IntelliForm-Signed"; public static final String ATTRIBUTES_ENTRY_VALUE = "false"; public static Attachment createXmlDaten() { - var attachment = new Attachment(); - attachment.getAttributes().add(createAttributesEntry()); - attachment.setContentType(XML_CONTENT_TYPE); - attachment.setId(XML_ID); - attachment.setName(XML_NAME); - attachment.setContent(XML_CONTENT); - return attachment; + return createXmlDatenWithContent(XML_CONTENT); } public static Attachment createPdf() { + return createAttachment(MetaAttachment.builder() + .id(PDF_ATTACHMENT_ID) + .name(PDF_ATTACHMENT_NAME) + .contentType(PDF_ATTACHMENT_CONTENT_TYPE) + .content(PDF_ATTACHMENT_CONTENT) + .build()); + } + + public static Attachment createPng() { + return createAttachment(MetaAttachment.builder() + .id(PNG_ATTACHMENT_ID) + .name(PNG_ATTACHMENT_NAME) + .contentType(PNG_ATTACHMENT_CONTENT_TYPE) + .content(PNG_ATTACHMENT_CONTENT) + .build()); + } + + private static Attachment createAttachment(MetaAttachment metaAttachment) { var attachment = new Attachment(); attachment.getAttributes().add(createAttributesEntry()); - attachment.setContent(PDF_ATTACHMENT_CONTENT); - attachment.setContentType(PDF_ATTACHMENT_CONTENT_TYPE); - attachment.setId(PDF_ATTACHMENT_ID); - attachment.setName(PDF_ATTACHMENT_NAME); + attachment.setContent(metaAttachment.content.getBytes()); + attachment.setContentType(metaAttachment.contentType); + attachment.setId(metaAttachment.id); + attachment.setName(metaAttachment.name); return attachment; } @@ -77,4 +130,59 @@ public class AttachmentTestFactory { attributesEntry.setValue(ATTRIBUTES_ENTRY_VALUE); return attributesEntry; } -} \ No newline at end of file + + public static List<Attachment> createManyAttachments(String xmlTemplateString, Map<String, String> templateValues, + String... attachmentParameterMatrix) { + + var metaAttachments = arrayToMetaAttachments(attachmentParameterMatrix); + + var allTemplateValues = Stream.concat( + templateValues.entrySet().stream(), + metaAttachments.stream().map(metaAttachment -> Map.entry(metaAttachment.templateId, metaAttachment.id)) + ).collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + var xmlFormString = fillTemplateString( + xmlTemplateString, + allTemplateValues + ); + + return Stream.concat( + Stream.of(createXmlDatenWithContent(xmlFormString)), + metaAttachments.stream().map(AttachmentTestFactory::createAttachment) + ).toList(); + } + + private static Attachment createXmlDatenWithContent(String content) { + return createAttachment(MetaAttachment.builder() + .id(XML_ATTACHMENT_ID) + .name(XML_NAME) + .contentType(XML_CONTENT_TYPE) + .content(content) + .build() + ); + } + + @Builder + private record MetaAttachment(String id, String name, String contentType, String content, String templateId) { + } + + private static List<MetaAttachment> arrayToMetaAttachments(String[] array) { + int parameterCount = 5; + if (array.length % parameterCount != 0) { + throw new IllegalArgumentException("Matrix length must be divisible by %d.".formatted(parameterCount)); + } + + return IntStream.range(0, array.length / parameterCount) + .boxed() + .map(row -> row * parameterCount) + .map(offset -> new MetaAttachment(array[offset], array[offset + 1], array[offset + 2], array[offset + 3], array[offset + 4])) + .toList(); + } + + private static String fillTemplateString(String templateString, Map<String, String> templateValues) { + return templateValues.entrySet().stream() + .reduce(templateString, + (currentString, entry) -> currentString.replace("${" + entry.getKey() + "}", entry.getValue()), + (s1, s2) -> s1); + } +} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdderTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdderTest.java deleted file mode 100644 index eb1f646706f25d8a2f7861e39092522f4ec8b578..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdderTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import static org.assertj.core.api.Assertions.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; -import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; -import lombok.SneakyThrows; - -class AttachmentsContentAdderTest { - - AttachmentsContentAdder service; - - private List<IncomingFileGroup> attachments; - - private List<IncomingFile> depositRequestFiles; - - @BeforeEach - void init() { - - service = new AttachmentsContentAdder(); - - attachments = List.of(IncomingFileGroupTestFactory.createBuilder().clearFiles() - .files(List.of(IncomingFileTestFactory.createBuilder().file(null).build())).build()); - - depositRequestFiles = List.of(IncomingFileTestFactory.create()); - } - - @SneakyThrows - @Test - void testAddContentToAttachments() { - List<IncomingFileGroup> attachmentsWithContent = service.addContentToAttachments(attachments, depositRequestFiles); - - assertThat(attachmentsWithContent.get(0).getFiles().get(0).getContentStream()).hasBinaryContent(IncomingFileTestFactory.CONTENT); - } -} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderReaderTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderReaderTest.java deleted file mode 100644 index eb435c85ecd0d0dc5214f7a595abc7bd9632f396..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderReaderTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -class CustomHeaderReaderTest { - - @InjectMocks - private CustomHeaderReader reader; - - @Mock - private Document document; - @Mock - private Element element; - @Mock - private Attr attribute; - - @BeforeEach - void setup() { - when(document.getDocumentElement()).thenReturn(element); - } - - @Test - void shouldNotAddIfNotPresent() { - var formData = reader.getHeader(document); - - assertThat(formData).isEmpty(); - } - - @Nested - class TestHeaderAdded { - - @BeforeEach - void setup() { - when(element.getAttributeNode(any())).thenReturn(attribute); - } - - @Test - void shouldAddPostfachId() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_POSTFACH_ID); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.POSTFACH_ID); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_POSTFACH_ID, CustomHeaderTestFactory.POSTFACH_ID); - } - - @Test - void shouldAddVorname() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_VORNAME); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.VORNAME); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_VORNAME, CustomHeaderTestFactory.VORNAME); - } - - @Test - void shouldAddNachname() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_NACHNAME); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.NACHNAME); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_NACHNAME, CustomHeaderTestFactory.NACHNAME); - } - - @Test - void shouldAddGeburtsname() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_GEBURTSNAME); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.GEBURTSNAME); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_GEBURTSNAME, CustomHeaderTestFactory.GEBURTSNAME); - } - - @Test - void shouldAddGeburtsort() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_GEBURTSORT); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.GEBURTSORT); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_GEBURTSORT, CustomHeaderTestFactory.GEBURTSORT); - } - - @Test - void shouldAddEmail() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_EMAIL); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.EMAIL); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_EMAIL, CustomHeaderTestFactory.EMAIL); - } - - @Test - void shouldAddTelefon() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_TELEFON); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.TELEFON); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_TELEFON, CustomHeaderTestFactory.TELEFON); - } - - @Test - void shouldAddStrasse() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_STRASSE); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.STRASSE); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_STRASSE, CustomHeaderTestFactory.STRASSE); - } - - @Test - void shouldAddPlz() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_PLZ); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.PLZ); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_PLZ, CustomHeaderTestFactory.PLZ); - } - - @Test - void shouldAddOrt() { - when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_ORT); - when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.ORT); - - var formData = reader.getHeader(document); - - assertThat(formData).containsEntry(CustomHeaderReader.HEADER_ORT, CustomHeaderTestFactory.ORT); - } - } - -} \ No newline at end of file diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderTestFactory.java deleted file mode 100644 index acb9fede61f17309e4417fac7149f5d03177c588..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderTestFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - - -import java.util.HashMap; -import java.util.Map; - -public class CustomHeaderTestFactory { - - public static final String POSTFACH_ID = "postfach_id"; - public static final String VORNAME = "vorname"; - public static final String NACHNAME = "nachname"; - public static final String GEBURTSNAME = "geburtsname"; - public static final String GEBURTSORT = "geburtsort"; - public static final String EMAIL = "email"; - public static final String TELEFON = "telefon"; - public static final String STRASSE = "strasse"; - public static final String PLZ = "plz"; - public static final String ORT = "ort"; - - public static Map<String, Object> create() { - var map = new HashMap<String, Object>(); - map.put(CustomHeaderReader.HEADER_POSTFACH_ID, POSTFACH_ID); - map.put(CustomHeaderReader.HEADER_VORNAME, VORNAME); - map.put(CustomHeaderReader.HEADER_NACHNAME, NACHNAME); - map.put(CustomHeaderReader.HEADER_GEBURTSNAME, GEBURTSNAME); - map.put(CustomHeaderReader.HEADER_GEBURTSORT, GEBURTSORT); - map.put(CustomHeaderReader.HEADER_EMAIL, EMAIL); - map.put(CustomHeaderReader.HEADER_TELEFON, TELEFON); - map.put(CustomHeaderReader.HEADER_STRASSE, STRASSE); - map.put(CustomHeaderReader.HEADER_PLZ, PLZ); - map.put(CustomHeaderReader.HEADER_ORT, ORT); - return map; - } - -} 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 new file mode 100644 index 0000000000000000000000000000000000000000..53aa6003c9e0595b8df9e4f534ca82c2f0e91b6e --- /dev/null +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2022 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.intelliform; + +import static de.ozgcloud.eingang.intelliform.AttachmentTestFactory.*; +import static de.ozgcloud.eingang.intelliform.DepositDataTestFactory.*; +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; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.io.FileUtils; +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.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Spy; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import lombok.SneakyThrows; + +class DepositDataMapperTest { + + @Spy + private DepositDataMapper mapper; + + @DisplayName("map to form data") + @Nested + class TestMapToFormData { + + @Captor + private ArgumentCaptor<Attachment> attachmentArgumentCaptor; + + private DepositData depositData; + + @DisplayName("with normal attachments") + @Nested + class TestWithNormalAttachments { + @BeforeEach + void mock() { + depositData = DepositDataTestFactory.create(ATTACHMENTS); + } + + @DisplayName("should throw technical exception if primary xml link is incorrect") + @Test + void shouldThrowTechnicalExceptionIfPrimaryXmlLinkIsIncorrect() { + depositData.setPrimaryDataAttachmentId("incorrect"); + + assertThatThrownBy(TestMapToFormData.this::doMapping) + .isInstanceOf(TechnicalException.class); + } + + @DisplayName("should use map to incoming file method") + @Test + void shouldUseMapToIncomingFileMethod() { + doMapping(); + verify(mapper, times(ATTACHMENTS.size())).mapAttachmentToIncomingFile(attachmentArgumentCaptor.capture()); + + assertThat(attachmentArgumentCaptor.getAllValues()).isEqualTo(ATTACHMENTS); + } + + @DisplayName("should return with representations") + @Test + void shouldReturnWithRepresentations() { + var formData = doMapping(); + + var incomingFileIds = formData.getRepresentations().stream().map(IncomingFile::getVendorId).toList(); + assertThat(incomingFileIds).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID); + } + + @DisplayName("should return with one attachment") + @Test + void shouldReturnWithOneAttachment() { + var formData = doMapping(); + + var incomingFileIds = formData.getAttachments().stream() + .flatMap(group -> group.getFiles().stream()) + .map(IncomingFile::getVendorId) + .toList(); + assertThat(incomingFileIds).containsExactly(PNG_ATTACHMENT_ID); + } + + @DisplayName("should return with attachment group name") + @Test + void shouldReturnWithAttachmentGroupName() { + var formData = doMapping(); + + var incomingFileIds = formData.getAttachments().stream() + .map(IncomingFileGroup::getName) + .toList(); + assertThat(incomingFileIds).containsExactly("Upload1"); + } + + @DisplayName("should return with number of representations") + @Test + void shouldReturnWithNumberOfRepresentations() { + var formData = doMapping(); + + assertThat(formData.getNumberOfRepresentations()).isEqualTo(2); + } + } + + @DisplayName("with duplicate keys") + @Nested + class TestWithDuplicateKeys { + @BeforeEach + void mock() { + depositData = DepositDataTestFactory.create(List.of( + withEmptyName(createXmlDaten()), + createXmlDaten(), + withEmptyName(createPdf()), + createPdf(), + withEmptyName(createPng()), + createPng() + )); + } + + private Attachment withEmptyName(Attachment attachment) { + attachment.setName(""); + return attachment; + } + + @DisplayName("should keep last entry for representations") + @Test + void shouldKeepLastEntryForRepresentations() { + var formData = doMapping(); + + var representationFiles = formData.getRepresentations(); + assertThat(getAttachmentVendorIds(representationFiles)).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID); + assertThat(getAttachmentFileNames(representationFiles)).containsExactly(XML_NAME, PDF_ATTACHMENT_NAME); + } + + @DisplayName("should keep last entry for attachments") + @Test + void shouldKeepLastEntryForAttachments() { + var formData = doMapping(); + + var attachmentFiles = formData.getAttachments().stream() + .map(IncomingFileGroup::getFiles) + .flatMap(List::stream) + .toList(); + assertThat(getAttachmentVendorIds(attachmentFiles)).containsExactly(PNG_ATTACHMENT_ID); + assertThat(getAttachmentFileNames(attachmentFiles)).containsExactly(PNG_ATTACHMENT_NAME); + } + + private List<String> getAttachmentFileNames(List<IncomingFile> incomingFileList) { + return incomingFileList.stream() + .map(IncomingFile::getName) + .toList(); + } + + private List<String> getAttachmentVendorIds(List<IncomingFile> incomingFileList) { + return incomingFileList.stream() + .map(IncomingFile::getVendorId) + .toList(); + } + } + + @DisplayName("with many attachments") + @Nested + class TestWithManyAttachments { + @BeforeEach + void mock() { + depositData = DepositDataTestFactory.create(MANY_ATTACHMENTS); + } + + @DisplayName("should return with representations") + @Test + void shouldReturnWithRepresentations() { + var formData = doMapping(); + + var incomingFileIds = formData.getRepresentations().stream() + .map(IncomingFile::getVendorId) + .toList(); + assertThat(incomingFileIds).containsExactly(XML_ATTACHMENT_ID); + } + + @DisplayName("should return with attachment groups") + @Test + void shouldReturnWithAttachmentGroups() { + var formData = doMapping(); + + var incomingFileIds = formData.getAttachments().stream() + .flatMap(group -> group.getFiles().stream()) + .map(IncomingFile::getVendorId) + .toList(); + assertThat(incomingFileIds).containsExactlyInAnyOrder( + DOCX1_ATTACHMENT_ID, + PDF_ATTACHMENT_ID, + DOCX2_ATTACHMENT_ID, + DOCX3_ATTACHMENT_ID, + DOCX4_ATTACHMENT_ID, + DOCX5_ATTACHMENT_ID, + DOCX6_ATTACHMENT_ID, + DOCX7_ATTACHMENT_ID, + DOCX8_ATTACHMENT_ID, + PDF2_ATTACHMENT_ID, + ODT_ATTACHMENT_ID, + JPG_ATTACHMENT_ID, + PNG_ATTACHMENT_ID + ); + } + } + + @DisplayName("with empty attachments") + @Nested + class TestWithEmptyAttachments { + @DisplayName("should throw technical exception") + @Test + void shouldThrowTechnicalException() { + depositData = DepositDataTestFactory.create(Collections.emptyList()); + + assertThatThrownBy(TestMapToFormData.this::doMapping) + .isInstanceOf(TechnicalException.class); + } + } + + private FormData doMapping() { + return mapper.mapToFormData(depositData); + } + + } + + @DisplayName("map deposit attachments to incoming files") + @Nested + class TestMapDepositAttachmentsToIncomingFiles { + @DisplayName("should keep entry order") + @Test + void shouldKeepEntryOrder() { + var depositData = DepositDataTestFactory.create(ATTACHMENTS); + + var incomingFileMap = mapper.mapDepositAttachmentsToIncomingFiles(depositData); + + var keys = incomingFileMap.keySet().stream().toList(); + assertThat(keys).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID, PNG_ATTACHMENT_ID); + } + + @DisplayName("should keep last entry for duplicate key") + @Test + void shouldKeepLastEntryForDuplicateKey() { + var depositData = DepositDataTestFactory.create(List.of( + AttachmentTestFactory.createXmlDaten(), + AttachmentTestFactory.createPdf(), + AttachmentTestFactory.createXmlDaten() + )); + + var incomingFileMap = mapper.mapDepositAttachmentsToIncomingFiles(depositData); + + var keys = incomingFileMap.keySet().stream().toList(); + assertThat(keys).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID); + } + } + + @DisplayName("map attachment to incoming file") + @Nested + class TestMapAttachmentToIncomingFile { + private Attachment attachment; + + @BeforeEach + void mock() { + attachment = AttachmentTestFactory.createXmlDaten(); + } + + @DisplayName("should have ID") + @Test + void shouldHaveId() { + var incomingFile = doMapping(); + + assertThat(incomingFile.getId()).isNotNull(); + } + + @DisplayName("should have vendor ID") + @Test + void shouldHaveVendorId() { + var incomingFile = doMapping(); + + assertThat(incomingFile.getVendorId()).isEqualTo(XML_ATTACHMENT_ID); + } + + @DisplayName("should have name") + @Test + void shouldHaveName() { + var incomingFile = doMapping(); + + assertThat(incomingFile.getName()).isEqualTo(XML_NAME); + } + + @DisplayName("should have content type") + @Test + void shouldHaveContentType() { + var incomingFile = doMapping(); + + assertThat(incomingFile.getContentType()).isEqualTo(XML_CONTENT_TYPE); + } + + @DisplayName("should have size") + @Test + void shouldHaveSize() { + var incomingFile = doMapping(); + + assertThat(incomingFile.getSize()).isEqualTo(XML_CONTENT.getBytes().length); + } + + @DisplayName("should have file with content") + @SneakyThrows + @Test + void shouldHaveFileWithContent() { + var incomingFile = doMapping(); + + var content = FileUtils.readFileToString(incomingFile.getFile(), Charset.defaultCharset()); + assertThat(content).isEqualTo(XML_CONTENT_STRING); + } + + private IncomingFile doMapping() { + return mapper.mapAttachmentToIncomingFile(attachment); + } + } + + @DisplayName("find attachment groups") + @Nested + class TestFindAttachmentGroups { + + private Document document; + + @BeforeEach + void mock() { + document = buildXMLDocument(""" + <myForm t:client-id="land"> + <Upload1> + <file content-type="image/png" description="" id="VendorId3333" length="155251">Image.png</file> + </Upload1> + <Upload2> + <file id="VendorId1111">name1.txt</file> + <file id="VendorId2222">name2.txt</file> + </Upload2> + <file id="VendorIdxxxx">namex.txt</file> + </myForm>"""); + } + + @DisplayName("should have groups with parent element name") + @Test + void shouldHaveGroupsWithParentElementName() { + var attachmentGroups = mapper.findAttachmentGroups(document); + + assertThat(attachmentGroups).containsOnlyKeys("Upload1", "Upload2", "myForm"); + } + + @DisplayName("should have Upload1 group with fileId") + @Test + void shouldHaveUpload1GroupWithFileId() { + var attachmentGroups = mapper.findAttachmentGroups(document); + + assertThat(attachmentGroups.get("Upload1")).containsExactly("VendorId3333"); + } + + @DisplayName("should have two fileIds in Upload2 group") + @Test + void shouldHaveTwoFileIdsInUpload2Group() { + var attachmentGroups = mapper.findAttachmentGroups(document); + + assertThat(attachmentGroups.get("Upload2")).containsExactly("VendorId1111", "VendorId2222"); + } + } + + private Document buildXMLDocument(String xmlString) { + try { + return DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(new InputSource(new StringReader(xmlString))); + } catch (ParserConfigurationException | IOException | SAXException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e6382bf2009f146b5fa4c176a8caa8c0f632d338 --- /dev/null +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataTestFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 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.intelliform; + +import static de.ozgcloud.eingang.intelliform.AttachmentTestFactory.*; + +import java.time.Instant; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import de.ozgcloud.common.test.TestUtils; + +public class DepositDataTestFactory { + + public static final List<Attachment> ATTACHMENTS = List.of( + AttachmentTestFactory.createXmlDaten(), + AttachmentTestFactory.createPdf(), + AttachmentTestFactory.createPng() + ); + + public static final List<Attachment> MANY_ATTACHMENTS = createManyAttachments( + TestUtils.loadTextFile("intelliform/XML-Daten-complex.template.xml"), + Map.of( + "oeid", ORGANISATIONSEINHEITEN_ID, + "uuid", UUID.randomUUID().toString(), + "transactionId", UUID.randomUUID().toString(), + "now", Instant.now().toString(), + "antragsteller_anrede", ANTRAGSTELLER_ANREDE, + "anrede_code", ANTRAGSTELLER_ANREDE_CODE, + "antragsteller_nachname", ANTRAGSTELLER_NACHNAME, + "antragsteller_vorname", "Max", + "antragsteller_email", "max.mustermann@example.com" + ), + DOCX1_ATTACHMENT_ID, "Document1.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx1", + PDF_ATTACHMENT_ID, "Document2.pdf", PDF_ATTACHMENT_CONTENT_TYPE, PDF_ATTACHMENT_CONTENT, "fileid-pdf1", + DOCX2_ATTACHMENT_ID, "Document3.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx2", + DOCX3_ATTACHMENT_ID, "Document4.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx3", + DOCX4_ATTACHMENT_ID, "Document5.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx4", + DOCX5_ATTACHMENT_ID, "Document6.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx5", + DOCX6_ATTACHMENT_ID, "Document7.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx6", + DOCX7_ATTACHMENT_ID, "Document8.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx7", + DOCX8_ATTACHMENT_ID, "Document9.docx", DOCX_ATTACHMENT_CONTENT_TYPE, DOCX_ATTACHMENT_CONTENT, "fileid-docx8", + PDF2_ATTACHMENT_ID, "Document9.pdf", PDF_ATTACHMENT_CONTENT_TYPE, PDF_ATTACHMENT_CONTENT, "fileid-pdf2", + ODT_ATTACHMENT_ID, "Document10.odt", ODT_ATTACHMENT_CONTENT_TYPE, "TestContent5", "fileid-odt1", + JPG_ATTACHMENT_ID, "Document11.jpg", "image/jpeg", "TestContent6", "fileid-jpg1", + PNG_ATTACHMENT_ID, "Document12.png", "image/png", "TestContent7", "fileid-png1"); + + public static DepositData create(Collection<Attachment> attachments) { + var depositData = new DepositData(); + depositData.setPrimaryDataAttachmentId(AttachmentTestFactory.XML_ATTACHMENT_ID); + depositData.getAttachments().addAll(attachments); + return depositData; + } +} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapperTest.java deleted file mode 100644 index 2ae6057c37562eedfee982df019ca6be54bcc7d0..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapperTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import static org.assertj.core.api.Assertions.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import de.ozgcloud.eingang.common.formdata.IncomingFile; - -class DepositRequestIncomingFileMapperTest { - - private DepositRequestIncomingFileMapper mapper; - - @BeforeEach - void init() { - - mapper = new DepositRequestIncomingFileMapper(); - } - - @Test - void validateFileCount() { - - List<IncomingFile> files = mapper.mapFiles(DepositTestFactory.create()); - - assertThat(files).isNotEmpty().hasSize(2); - } - - @Test - void validateFile1() { - - List<IncomingFile> files = mapper.mapFiles(DepositTestFactory.create()); - - IncomingFile file = files.get(0); - assertThat(file.getContentStream()).hasBinaryContent(AttachmentTestFactory.XML_CONTENT); - assertThat(file.getContentType()).isEqualTo(AttachmentTestFactory.XML_CONTENT_TYPE); - assertThat(file.getVendorId()).isEqualTo(AttachmentTestFactory.XML_ID); - assertThat(file.getName()).isEqualTo(AttachmentTestFactory.XML_NAME); - assertThat(file.getId()).isNotNull(); - } -} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositTestFactory.java deleted file mode 100644 index 174569a3e12d247dd7dc3ac4d9e9ca609298f858..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositTestFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import java.util.List; - -import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; - -public class DepositTestFactory { - - public static final String ATTACHMENT1_NAME = IncomingFileTestFactory.NAME; - public static final String ATTACHMENT1_ID = IncomingFileTestFactory.VENDOR_ID; - public static final String ATTACHMENT1_CONTENT_TYPE = IncomingFileTestFactory.CONTENT_TYPE; - public static final byte[] ATTACHMENT1_CONTENT = IncomingFileTestFactory.CONTENT; - - public static final String ATTACHMENT2_NAME = "Scan1.pdf"; - public static final String ATTACHMENT2_ID = "VendorId2222"; - public static final String ATTACHMENT2_CONTENT_TYPE = "application/pdf"; - public static final byte[] ATTACHMENT2_CONTENT = "TestContent2".getBytes(); - - public static final List<Attachment> ATTACHMENTS = List.of(AttachmentTestFactory.createXmlDaten(), AttachmentTestFactory.createPdf()); - - public static Deposit create() { - return DepositTestFactory.withAttachments(ATTACHMENTS); - } - - static Deposit withData(DepositData data) { - Deposit deposit = new Deposit(); - data.setPrimaryDataAttachmentId(AttachmentTestFactory.XML_ID); - deposit.setData(data); - - return deposit; - } - - static Deposit withAttachments(List<Attachment> attachments) { - Deposit deposit = DepositTestFactory.withData(new DepositData()); - deposit.getData().getAttachments().addAll(attachments); - return deposit; - } -} 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 2e87bcbd6b297b71c4ece2afa451f258dcae239a..524f388ca41061d7abcfe8b535d4f78853df2081 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 @@ -23,13 +23,28 @@ */ package de.ozgcloud.eingang.intelliform; +import static de.ozgcloud.eingang.intelliform.AttachmentTestFactory.*; +import static de.ozgcloud.eingang.intelliform.DepositDataTestFactory.*; +import static de.ozgcloud.eingang.intelliform.FormDataEndpoint.*; import static de.ozgcloud.eingang.intelliform.XmlDaten1Container.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Collection; +import java.util.List; import java.util.Optional; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import jakarta.xml.bind.JAXBElement; + +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -41,6 +56,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.ws.test.server.MockWebServiceClient; import org.springframework.ws.test.server.RequestCreators; import org.springframework.ws.test.server.ResponseActions; @@ -49,6 +65,7 @@ import org.springframework.ws.test.server.ResponseMatchers; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; import de.ozgcloud.eingang.router.VorgangRemoteService; +import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller; import de.ozgcloud.vorgang.vorgang.GrpcEingang; import de.ozgcloud.vorgang.vorgang.GrpcFormData; import de.ozgcloud.vorgang.vorgang.GrpcIncomingFile; @@ -64,9 +81,11 @@ class FormDataEndpointITCase { private final static String RESPONSE = "EinfachesFormularZweiAnhaengeSoapResponse.xml"; private static final String SOAP_REQUEST_OTHER_NAME = "XML-Daten-1-other_name_SoapRequest.xml"; + private static Jaxb2Marshaller marshaller; @Autowired private ApplicationContext applicationContext; + @MockBean private VorgangRemoteService vorgangRemoteService; @@ -79,11 +98,186 @@ class FormDataEndpointITCase { private MockWebServiceClient mockClient; + private DepositData depositData; + + @BeforeAll + static void setupMarshaller() { + marshaller = new Jaxb2Marshaller(); + marshaller.setPackagesToScan("de.ozgcloud.eingang.intelliform"); + } + @BeforeEach void initTest() { mockClient = MockWebServiceClient.createClient(applicationContext); } + @DisplayName("send antrag with many attachments") + @Nested + class TestSendAntragWithManyAttachments { + + @BeforeEach + void mock() { + depositData = DepositDataTestFactory.create(MANY_ATTACHMENTS); + } + + @DisplayName("should map antragsteller nachname") + @Test + void shouldMapAntragstellerNachname() { + sendDepositAndCaptureCreateVorgang(); + + var antragsteller = getCapturedAntragsteller(); + assertThat(antragsteller.getNachname()).isEqualTo(ANTRAGSTELLER_NACHNAME); + } + + @DisplayName("should map antragsteller anrede") + @Test + void shouldMapAntragstellerAnrede() { + sendDepositAndCaptureCreateVorgang(); + + var antragsteller = getCapturedAntragsteller(); + assertThat(antragsteller.getAnrede()).isEqualTo(ANTRAGSTELLER_ANREDE); + } + + private GrpcAntragsteller getCapturedAntragsteller() { + return grpcEingangCaptor.getValue().getAntragsteller(); + } + + @DisplayName("should have one representation") + @Test + void shouldHaveOneRepresentation() { + sendDepositAndCaptureCreateVorgang(); + + var eingang = grpcEingangCaptor.getValue(); + var representationVendorIds = eingang.getRepresentationsList().stream() + .map(GrpcIncomingFile::getVendorId) + .toList(); + assertThat(representationVendorIds).containsExactly(XML_ATTACHMENT_ID); + } + + @DisplayName("should have attachments") + @Test + void shouldHaveAttachments() { + sendDepositAndCaptureCreateVorgang(); + + var eingang = grpcEingangCaptor.getValue(); + var attachmentVendorIds = eingang.getAttachmentsList().stream() + .map(GrpcIncomingFileGroup::getFilesList) + .flatMap(Collection::stream) + .map(GrpcIncomingFile::getVendorId) + .toList(); + assertThat(attachmentVendorIds).containsExactlyInAnyOrder( + DOCX1_ATTACHMENT_ID, + PDF_ATTACHMENT_ID, + DOCX2_ATTACHMENT_ID, + DOCX3_ATTACHMENT_ID, + DOCX4_ATTACHMENT_ID, + DOCX5_ATTACHMENT_ID, + DOCX6_ATTACHMENT_ID, + DOCX7_ATTACHMENT_ID, + DOCX8_ATTACHMENT_ID, + PDF2_ATTACHMENT_ID, + ODT_ATTACHMENT_ID, + JPG_ATTACHMENT_ID, + PNG_ATTACHMENT_ID + ); + } + + @DisplayName("should have organisationseinheitenID") + @Test + void shouldHaveOrganisationseinheitenId() { + sendDepositAndCaptureCreateVorgang(); + + var oeid = organisationsEinheitIdCaptor.getValue(); + assertThat(oeid).hasValue(ORGANISATIONSEINHEITEN_ID); + + var eingang = grpcEingangCaptor.getValue(); + assertThat(eingang.getZustaendigeStelle().getOrganisationseinheitenId()).isEqualTo(ORGANISATIONSEINHEITEN_ID); + } + + } + + @DisplayName("with duplicate keys") + @Nested + class TestWithDuplicateKeys { + @BeforeEach + void mock() { + depositData = DepositDataTestFactory.create(List.of( + withEmptyName(createXmlDaten()), + createXmlDaten(), + withEmptyName(createPdf()), + createPdf(), + withEmptyName(createPng()), + createPng() + )); + } + + private Attachment withEmptyName(Attachment attachment) { + attachment.setName(""); + return attachment; + } + + @DisplayName("should keep last entry for representations") + @Test + void shouldKeepLastEntryForRepresentations() { + sendDepositAndCaptureCreateVorgang(); + + var eingang = grpcEingangCaptor.getValue(); + var representationFiles = eingang.getRepresentationsList(); + assertThat(getAttachmentVendorIds(representationFiles)).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID); + assertThat(getAttachmentFileNames(representationFiles)).containsExactly(XML_NAME, PDF_ATTACHMENT_NAME); + } + + @DisplayName("should keep last entry for attachments") + @Test + void shouldKeepLastEntryForAttachments() { + sendDepositAndCaptureCreateVorgang(); + + var eingang = grpcEingangCaptor.getValue(); + var attachmentFiles = eingang.getAttachmentsList().stream() + .map(GrpcIncomingFileGroup::getFilesList) + .flatMap(List::stream) + .toList(); + assertThat(getAttachmentVendorIds(attachmentFiles)).containsExactly(PNG_ATTACHMENT_ID); + assertThat(getAttachmentFileNames(attachmentFiles)).containsExactly(PNG_ATTACHMENT_NAME); + } + + private List<String> getAttachmentFileNames(List<GrpcIncomingFile> incomingFileList) { + return incomingFileList.stream() + .map(GrpcIncomingFile::getName) + .toList(); + } + + private List<String> getAttachmentVendorIds(List<GrpcIncomingFile> incomingFileList) { + return incomingFileList.stream() + .map(GrpcIncomingFile::getVendorId) + .toList(); + } + } + + @SneakyThrows + private void sendDepositAndCaptureCreateVorgang() { + mockClient.sendRequest(RequestCreators.withPayload(createEnvelopeSourceFromDepositData(depositData))) + .andExpect(ResponseMatchers.noFault()) + .andExpect(ResponseMatchers.payload(getResource(RESPONSE))); + + verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), grpcEingangCaptor.capture(), organisationsEinheitIdCaptor.capture()); + } + + @SneakyThrows + private Source createEnvelopeSourceFromDepositData(DepositData depositData) { + Deposit deposit = new Deposit(); + deposit.setData(depositData); + + JAXBElement<Deposit> depositJAXBElement = new JAXBElement<>( + new QName(NAMESPACE_URI, PAYLOAD_LOCAL_PART), + Deposit.class, + deposit); + + var stringWriter = new StringWriter(); + marshaller.marshal(depositJAXBElement, new StreamResult(stringWriter)); + return new StreamSource(new StringReader(stringWriter.toString())); + } + @DisplayName("Send antrag with attachments") @Nested class TestAntragWithAttachments { diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java index c6c9381d3ca42453ede63033b277c7e1d00261ef..b58584e84b0ccf8362a448a506449d67bc7a23c2 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java @@ -45,20 +45,20 @@ import de.ozgcloud.eingang.semantik.SemantikAdapter; class FormDataEndpointTest { @InjectMocks - private FormDataEndpoint formdataEndpoint; + private FormDataEndpoint formdataEndpointIntelli; @Mock - private SemantikFormDataMapper semantikFormDataMapper; + private DepositDataMapper depositDataMapper; @Mock private SemantikAdapter semantikAdapter; @BeforeEach void init() throws SAXException, IOException, ParserConfigurationException { - when(semantikFormDataMapper.mapToFormData(any())).thenReturn(FormDataTestFactory.create()); + when(depositDataMapper.mapToFormData(any())).thenReturn(FormDataTestFactory.create()); } @Test void testDepositFormData() throws SAXException, IOException, ParserConfigurationException, URISyntaxException { - var response = formdataEndpoint.inputFormData(buildRequest("intelliform/XML-Daten-1.xml")); + var response = formdataEndpointIntelli.inputFormData(buildRequest("intelliform/XML-Daten-1.xml")); assertThat(response).isNotNull(); } diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapperTest.java deleted file mode 100644 index 05d11ea152de2367bb23d51555764a15083103d9..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapperTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import static org.assertj.core.api.Assertions.*; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.List; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import de.ozgcloud.common.test.TestUtils; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; - -class FormDataIncomingFileMapperTest { - - FormDataIncomingFileMapper mapper = new FormDataIncomingFileMapper(); - - private Document document; - - @Test - void testBuildParentNodeName() { - - assertThat(mapper.buildParentNodeName("datei_ausweis-item")).isEqualTo("datei_ausweis"); - assertThat(mapper.buildParentNodeName("datei_ausweis")).isEqualTo("datei_ausweis"); - assertThat(mapper.buildParentNodeName("datei_-item-ausweis")).isEqualTo("datei_-item-ausweis"); - } - - @Nested - class TestEinfachesFormularMitZweiAnhaengen { - - private static final String GROUP1NAME = "Upload1"; - private static final String GROUP2NAME = "Upload2"; - - List<IncomingFileGroup> attachments; - - @BeforeEach - void init() throws ParserConfigurationException, SAXException, IOException { - - String xml = TestUtils.loadTextFile("intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml"); - - document = buildDocument(xml); - - attachments = mapper.mapAttachments(document); - } - - @Test - void validateAttachmentGroupCount() { - - assertThat(attachments).hasSize(2); - } - - @Test - void validateGroup1Name() { - - assertThat(attachments.get(0).getName()).isEqualTo(GROUP1NAME); - } - - @Test - void validateGroup1FilesCount() { - - assertThat(attachments.get(0).getFiles()).hasSize(1); - } - - @Test - void validateGroup1File() { - - IncomingFile file = attachments.get(0).getFiles().get(0); - - assertThat(file.getId()).isNotNull().hasSize(36); - assertThat(file.getVendorId()).isEqualTo("assistants.E0FBA361C191F8B723949467AE302BEA24E4745E"); - assertThat(file.getName()).isEqualTo("Helge1.jpg"); - assertThat(file.getContentType()).isEqualTo("image/jpeg"); - assertThat(file.getSize()).isEqualTo(155251); - } - - @Test - void validateGroup2Name() { - - assertThat(attachments.get(1).getName()).isEqualTo(GROUP2NAME); - } - - @Test - void validateGroup2FilesCount() { - - assertThat(attachments.get(1).getFiles()).hasSize(1); - } - - @Test - void validateGroup2File() { - - IncomingFile file = attachments.get(1).getFiles().get(0); - - assertThat(file.getId()).isNotNull().hasSize(36); - assertThat(file.getVendorId()).isEqualTo("assistants.52D79E5B2118D1740045AB87151535DCAD24E9A7"); - assertThat(file.getName()).isEqualTo("Helgetext2.odt"); - assertThat(file.getContentType()).isEqualTo("application/vnd.oasis.opendocument.text"); - assertThat(file.getSize()).isEqualTo(7993); - } - } - - @Nested - class TestEinfachesFormularMitZweiAnhaengenVerschachtelt { - - private static final String GROUP1NAME = "datei_ausweis"; - private static final String GROUP2NAME = "datei_meldebestaetigung"; - - List<IncomingFileGroup> attachments; - - @BeforeEach - void init() throws ParserConfigurationException, SAXException, IOException { - - String xml = TestUtils.loadTextFile("intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml"); - - document = buildDocument(xml); - - attachments = mapper.mapAttachments(document); - } - - @Test - void validateAttachmentGroupCount() { - - assertThat(attachments).hasSize(2); - } - - @Test - void validateGroup1Name() { - - assertThat(attachments.get(0).getName()).isEqualTo(GROUP1NAME); - } - - @Test - void validateGroup1FilesCount() { - - assertThat(attachments.get(0).getFiles()).hasSize(2); - } - - @Test - void validateGroup1File1() { - - IncomingFile file = attachments.get(0).getFiles().get(0); - - assertThat(file.getId()).isNotNull().hasSize(36); - assertThat(file.getVendorId()).isEqualTo("assistants.21B483DAA2DC7900C1D1135E566D0F672CB42832"); - assertThat(file.getName()).isEqualTo("20210326_133516[1].jpg"); - assertThat(file.getContentType()).isEqualTo("image/jpeg"); - assertThat(file.getSize()).isEqualTo(1184319); - } - - @Test - void validateGroup1File2() { - - IncomingFile file = attachments.get(0).getFiles().get(1); - - assertThat(file.getId()).isNotNull().hasSize(36); - assertThat(file.getVendorId()).isEqualTo("assistants.2F1FF737CF4F23191C1952091CB342254EE22A37"); - assertThat(file.getName()).isEqualTo("20210326_133526[1].jpg"); - assertThat(file.getContentType()).isEqualTo("image/jpeg"); - assertThat(file.getSize()).isEqualTo(1384037); - } - - @Test - void validateGroup2Name() { - - assertThat(attachments.get(1).getName()).isEqualTo(GROUP2NAME); - } - - @Test - void validateGroup2FilesCount() { - - assertThat(attachments.get(1).getFiles()).hasSize(1); - } - - @Test - void validateGroup2File() { - - IncomingFile file = attachments.get(1).getFiles().get(0); - - assertThat(file.getId()).isNotNull().hasSize(36); - assertThat(file.getVendorId()).isEqualTo("assistants.B20451156C677116B91A4EF2D1E859837B6CE510"); - assertThat(file.getName()).isEqualTo("20210324_103054[1].jpg"); - assertThat(file.getContentType()).isEqualTo("image/jpeg"); - assertThat(file.getSize()).isEqualTo(3066416); - } - } - - private Document buildDocument(String xml) throws ParserConfigurationException, SAXException, IOException { - - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - - docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document document = docBuilder.parse(new ByteArrayInputStream(xml.getBytes())); - - // optional, but recommended - // http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work - document.getDocumentElement().normalize(); - - return document; - } - -} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculatorTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculatorTest.java deleted file mode 100644 index 36ac0cb7e2cff2cd68c210262b7d1360b8a68d9e..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculatorTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import static org.assertj.core.api.Assertions.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; -import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; - -class RepresentationsCalculatorTest { - - private static final String REPRESENTATION_VENDOR_ID_1 = "REPRESENTATION_VENDOR_ID_1"; - private static final String REPRESENTATION_VENDOR_ID_2 = "REPRESENTATION_VENDOR_ID_2"; - - private RepresentationsCalculator service; - - @BeforeEach - void init() { - - service = new RepresentationsCalculator(); - } - - @Nested - class CalculateRepresentations { - - private List<IncomingFile> representations; - - @BeforeEach - void init() { - - List<IncomingFile> depositDataFiles = List.of( - IncomingFileTestFactory.createBuilder().vendorId(REPRESENTATION_VENDOR_ID_1).build(), - IncomingFileTestFactory.create(), - IncomingFileTestFactory.createBuilder().vendorId(REPRESENTATION_VENDOR_ID_2).build()); - - List<IncomingFileGroup> formDataFileGroups = List.of(IncomingFileGroupTestFactory.create()); - - representations = service.calculateRepresentations(formDataFileGroups, depositDataFiles); - } - - @Test - void calculateRepresentations() { - - assertThat(representations).hasSize(2); - } - - @Test - void validateRepresentation1() { - - assertThat(representations.get(0).getVendorId()).isEqualTo(REPRESENTATION_VENDOR_ID_1); - } - - @Test - void validateRepresentation2() { - - assertThat(representations.get(1).getVendorId()).isEqualTo(REPRESENTATION_VENDOR_ID_2); - } - } -} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapperTest.java deleted file mode 100644 index 3bf90315f3d0be4e23ea2de093908455ad32b18e..0000000000000000000000000000000000000000 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapperTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2022 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.intelliform; - -import static de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory.*; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.parsers.ParserConfigurationException; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.xml.sax.SAXException; - -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper; - -class SemantikFormDataMapperTest { - - private SemantikFormDataMapper mapper; - - @Mock - private CustomHeaderReader customHeaderReader; - - @BeforeEach - void setup() { - mapper = new SemantikFormDataMapper(new XmlToJavaMapsMapper(), new FormDataIncomingFileMapper(), - new RepresentationsCalculator(), new DepositRequestIncomingFileMapper(), new AttachmentsContentAdder(), customHeaderReader); - } - - @Nested - class TestMapFormData { - - private final Deposit deposit = DepositTestFactory.create(); - - @Test - void shouldMapIdField() throws SAXException, IOException, ParserConfigurationException { - var formData = mapToFormData(deposit); - - assertThat(formData.getId()).isNotNull(); - } - - @Test - void shouldRemoveFileReferences() { - Map<String, Object> formDataMap = new HashMap<>(Map.of(FILE_REF1, Map.of(SemantikFormDataMapper.FILE, Map.of(ID, VENDOR_ID_XXX)))); - - mapper.removeMappedFileReferences(FILE_GROUPS, formDataMap); - - assertThat(formDataMap).doesNotContainKey(FILE_REF1); - } - - @Nested - class TestMapDepositRepresentations { - - @Test - void shouldMap() throws SAXException, IOException, ParserConfigurationException { - var formData = mapToFormData(deposit); - - assertThat(getRepresentations(formData)).hasSize(2); - } - - @Test - void shouldContainsXmlData() { - var formData = mapToFormData(deposit); - - var xmlRepresentation = getRepresentations(formData).stream() - .filter(xml -> xml.getContentType().equals(AttachmentTestFactory.XML_CONTENT_TYPE)).findFirst(); - assertThat(xmlRepresentation).isPresent(); - } - - @Test - void shouldContainsPdfData() { - var formData = mapToFormData(deposit); - - var pdfRepresentation = getRepresentations(formData).stream() - .filter(pdf -> pdf.getContentType().equals(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT_TYPE)).findFirst(); - assertThat(pdfRepresentation).isPresent(); - } - - @Test - void shouldContainsPdfAttributes() { - var formData = mapToFormData(deposit); - - var pdfAttachment = getRepresentations(formData).stream() - .filter(pdf -> pdf.getContentType().equals(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT_TYPE)).findFirst(); - - assertThat(pdfAttachment).isPresent(); - assertThat(pdfAttachment.get().getContentType()).isEqualTo(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT_TYPE); - assertThat(pdfAttachment.get().getVendorId()).isEqualTo(AttachmentTestFactory.PDF_ATTACHMENT_ID); - assertThat(pdfAttachment.get().getName()).isEqualTo(AttachmentTestFactory.PDF_ATTACHMENT_NAME); - assertThat(pdfAttachment.get().getContentStream()).hasBinaryContent(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT); - } - - @SuppressWarnings("unchecked") - private List<IncomingFile> getRepresentations(FormData formData) { - return (List<IncomingFile>) ((Map<String, Object>) formData.getFormData().get(FilesMapperHelper.FIELD_NAME_MAPPED_FILES)) - .get(FilesMapperHelper.REPRESENTATIONS); - } - } - - @Nested - class TestMapHeader { - - @Test - void shouldMapHeader() { - var formData = mapToFormData(deposit); - - var formHeader = getHeader(formData); - assertThat(formHeader) - .containsEntry(SemantikFormDataMapper.HEADER_ID, "20201118365670866101") - .containsEntry(SemantikFormDataMapper.HEADER_TIMESTAMP, "2020-11-18T09:09:27.627Z") - .containsEntry(SemantikFormDataMapper.HEADER_FORM_ID, "waffen/kleinerWaffenschein") - .containsEntry(SemantikFormDataMapper.HEADER_FORM, "Kleiner Waffenschein gem. § 10 Abs. 4 Satz 4 Waffengesetz (WaffG)") - .containsEntry(SemantikFormDataMapper.HEADER_SENDER, "afm.schleswig-holstein.de") - .containsEntry(SemantikFormDataMapper.HEADER_CUSTOMER, "Einheitlicher Ansprechpartner") - .containsEntry(SemantikFormDataMapper.HEADER_CUSTOMER_ID, "ea-sh") - .containsEntry(SemantikFormDataMapper.HEADER_CLIENT, "Schleswig-Holstein") - .containsEntry(SemantikFormDataMapper.HEADER_CLIENT_ID, "land"); - } - - @Test - void shouldAddBayernHeader() { - Map<String, Object> bayernHeader = Map.of(CustomHeaderReader.HEADER_POSTFACH_ID, CustomHeaderTestFactory.POSTFACH_ID); - when(customHeaderReader.getHeader(any())).thenReturn(bayernHeader); - - var formData = mapToFormData(deposit); - - verify(customHeaderReader).getHeader(any()); - assertThat(getHeader(formData)).containsEntry(CustomHeaderReader.HEADER_POSTFACH_ID, CustomHeaderTestFactory.POSTFACH_ID); - } - - @SuppressWarnings("unchecked") - private Map<String, Object> getHeader(FormData formData) { - return (Map<String, Object>) formData.getFormData().get(SemantikFormDataMapper.HEADER_FIELD); - } - } - - private FormData mapToFormData(Deposit deposit) { - return mapper.mapToFormData(deposit); - } - } -} \ No newline at end of file diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten-complex.template.xml b/intelliform-adapter/src/test/resources/intelliform/XML-Daten-complex.template.xml new file mode 100644 index 0000000000000000000000000000000000000000..df72b46d6663a9dc61710d70e8a7135e9368bd67 --- /dev/null +++ b/intelliform-adapter/src/test/resources/intelliform/XML-Daten-complex.template.xml @@ -0,0 +1,316 @@ +<myForm + xmlns:pdf="http://xmlns.cit.de/assistants/pdf" + xmlns:t="http://xmlns.cit.de/intelliform/transaction" + xmlns:u="http://xmlns.cit.de/intelliform/user" t:uuid="${uuid}" t:id="Gewerbeanmeldung-${transactionId}" t:timestamp="${now}" t:sender="stage.afm.schleswig-holstein.de" t:form="Gewerbeanmeldung" t:form-id="eGewerbe/eGewerbeAnmeldung" t:customer="Einheitlicher Ansprechpartner" t:customer-id="ea-sh" t:client="Schleswig-Holstein" t:client-id="land" u:FamilyNames="${antragsteller_nachname}" u:PrincipalType="Citizen" u:Username="${antragsteller_email}" u:CitizenProfileType="Standard" u:username="51522620-03d2-4507-b1f0-08d86920efed" u:GivenNames="${antragsteller_vorname}" u:AssuranceLevel="Low" u:displayName="${antragsteller_vorname} ${antragsteller_nachname}" u:mailAddress="${antragsteller_email}" u:EmailAddress="${antragsteller_email}" u:firstName="${antragsteller_vorname}" u:lastName="${antragsteller_nachname}" t:required-login-level="LOW" t:effective-login-level="LOW"> + <GueltigAb>2021-12-01</GueltigAb> + <GrundAnmeldungSchluessel>01</GrundAnmeldungSchluessel> + <antragsteller> + <pers_anrede>${antragsteller_anrede}$${anrede_code}</pers_anrede> + <pers_nachname>${antragsteller_nachname}</pers_nachname> + <pers_vorname>${antragsteller_vorname}</pers_vorname> + <pers_geburtsname>${antragsteller_nachname}</pers_geburtsname> + <pers_geburtsdatum>2000-01-01</pers_geburtsdatum> + <pers_geburtsort>Hamburg</pers_geburtsort> + <pers_geburtsland>deutsch$Deutschland$000</pers_geburtsland> + <pers_staatsangehoerigkeit>deutsch$Deutschland$000</pers_staatsangehoerigkeit> + <b_anrede>${antragsteller_anrede}</b_anrede> + <b_anrede_schluesselnr>03</b_anrede_schluesselnr> + <b_geburtsland>Deutschland</b_geburtsland> + <b_geburtsland_signatur>000</b_geburtsland_signatur> + <b_staatsangehoerigkeit>deutsch</b_staatsangehoerigkeit> + <b_staatsangehoerigkeit_signatur>000</b_staatsangehoerigkeit_signatur> + <sh_strasse>Teststrasse</sh_strasse> + <sh_hausnummer>1000</sh_hausnummer> + <sh_plz>23795</sh_plz> + <ort_auswahl>9007404$01060005</ort_auswahl> + <ort>Bad Segeberg</ort> + <GebietID>9007404</GebietID> + <GebietBEZEICHNUNG>Bad Segeberg</GebietBEZEICHNUNG> + <GebietGNR94_GNR>01060005</GebietGNR94_GNR> + <staat>000</staat> + <iso3166numerisch>276</iso3166numerisch> + <kont_telefonnummer/> + <kont_mobilnummer/> + <kont_telefaxnummer/> + <kont_email>${antragsteller_email}</kont_email> + <kont_demail/> + <persoenlicheEignung> + <maengelvorhanden>false</maengelvorhanden> + <ermittlungsverfahren>false</ermittlungsverfahren> + <MitgliedschaftInVerboternerVereinigung>false</MitgliedschaftInVerboternerVereinigung> + </persoenlicheEignung> + </antragsteller> + <AnliegenID>8938634</AnliegenID> + <nameid>51522620-03d2-4507-b1f0-08d86920efed</nameid> + <rest_response_name>[{"membercontext":"51522620-03d2-4507-b1f0-08d86920efed","memberscope":[{"tenant":"SH","mailboxguid":"6824d573-ff26-434d-81ae-2c36740e3cb4","mailboxname":"","mailboxdescription":"","mailboxtype":1,"guid":"00000000-0000-0000-0000-000000000000","id":8121155}]}]</rest_response_name> + <mailboxguid>6824d573-ff26-434d-81ae-2c36740e3cb4</mailboxguid> + <NiederlassungArt>1</NiederlassungArt> + <IstReisegewerbe>true</IstReisegewerbe> + <BetriebArtIndustrie>false</BetriebArtIndustrie> + <BetriebArtHandwerk>true</BetriebArtHandwerk> + <BetriebArtHandel>false</BetriebArtHandel> + <BetriebArtSonstiges>false</BetriebArtSonstiges> + <rechtsform>nicht eingetragenes Einzelunternehmen</rechtsform> + <rfm>180</rfm> + <registerart/> + <min2gesellschafter>false</min2gesellschafter> + <gesetzlichervertreter>Inhaber</gesetzlichervertreter> + <Betrieb> + <ID>577575</ID> + <geschaeftsbezeichnung>Test</geschaeftsbezeichnung> + <EintragungPLZ/> + <EintragungOrt/> + <GerichtSchluessel/> + </Betrieb> + <sh_strasse>Hauptstraße</sh_strasse> + <sh_zusatz>oben links</sh_zusatz> + <sh_hausnummer>10</sh_hausnummer> + <sh_plz>24534</sh_plz> + <ort_auswahl>9006404$01004000</ort_auswahl> + <sh_ortsteil>Einfeld</sh_ortsteil> + <ort>Neumünster</ort> + <GebietID>9006404</GebietID> + <GebietBEZEICHNUNG>Neumünster</GebietBEZEICHNUNG> + <GebietGNR94_GNR>01004000</GebietGNR94_GNR> + <staat>000</staat> + <iso3166numerisch>276</iso3166numerisch> + <kont_telefonnummer>01234/332211</kont_telefonnummer> + <kont_telefaxnummer>01234/112233</kont_telefaxnummer> + <kont_email>${antragsteller_email}</kont_email> + <kont_demail>ea-poststelle@ea-sh.de-mail.de</kont_demail> + <kont_homepage>www.meineHomepage.de</kont_homepage> + <b_kont_vorwahl_telefon>01234</b_kont_vorwahl_telefon> + <b_kont_telefon>332211</b_kont_telefon> + <b_kont_vorwahl_telefax>01234</b_kont_vorwahl_telefax> + <b_kont_telefax>112233</b_kont_telefax> + <TaetigkeitenGesamt> + <TaetigkeitenGesamt-item> + <auswahl_oberbegriff>C</auswahl_oberbegriff> + <auswahl_kategorie>10</auswahl_kategorie> + <check_taetigkeitsschwerpunkt>true</check_taetigkeitsschwerpunkt> + <a_taetigkeit>ausgewählte Tätigkeit</a_taetigkeit> + <b_oberbegriff>C Verarbeitendes Gewerbe</b_oberbegriff> + <b_kategorie>10 Herstellung von Nahrungs- und Futtermitteln</b_kategorie> + <b_unterklasse>10.12.0 Schlachten von Geflügel</b_unterklasse> + <b_unterklasse_schluessel>10.12.0</b_unterklasse_schluessel> + <b_inkl>- Betrieb von Schlachthäusern, in denen Geflügel geschlachtet, zugerichtet und verpackt wird - Herstellung von frischem oder gefrorenem Geflügelfleisch in Einzelportionen - Auslassen von Geflügelfetten - Gewinnung von Federn und Daunen</b_inkl> + </TaetigkeitenGesamt-item> + <TaetigkeitenGesamt-item> + <auswahl_oberbegriff>D</auswahl_oberbegriff> + <auswahl_kategorie>35</auswahl_kategorie> + <check_taetigkeitsschwerpunkt>false</check_taetigkeitsschwerpunkt> + <a_taetigkeit>ausgewählte Tätigkeit 2</a_taetigkeit> + <b_oberbegriff>D Energieversorgung</b_oberbegriff> + <b_kategorie>35 Energieversorgung</b_kategorie> + <b_unterklasse>35.11.1 Elektrizitätserzeugung ohne Verteilung</b_unterklasse> + <b_unterklasse_schluessel>35.11.1</b_unterklasse_schluessel> + <b_inkl/> + </TaetigkeitenGesamt-item> + </TaetigkeitenGesamt> + <IstNebenerwerb>true</IstNebenerwerb> + <AnzahlVollzeitBeschaeftigte>3</AnzahlVollzeitBeschaeftigte> + <AnzahlTeilzeitBeschaeftigte>3</AnzahlTeilzeitBeschaeftigte> + <BeteiligtePerson> + <BeteiligtePerson-item> + <personFunktion>1</personFunktion> + <personFunktionText>Einzelgewerbetreibender</personFunktionText> + <doktorgradSchluessel>01</doktorgradSchluessel> + <doktorgrad>Prof.</doktorgrad> + <familienname>${antragsteller_nachname}</familienname> + <vorname>Test</vorname> + <geschlechtText>weiblich</geschlechtText> + <geschlecht>2</geschlecht> + <geburtsname>Geburtsname</geburtsname> + <geburtsdatum>2000-01-01</geburtsdatum> + <geburtsort>Bremen</geburtsort> + <geburtsland>Deutschland</geburtsland> + <geburtslandSchluesel>000</geburtslandSchluesel> + <staatsangehoerigkeit>deutsch</staatsangehoerigkeit> + <staatsangehoerigkeitSchluessel>000</staatsangehoerigkeitSchluessel> + <adr_strasse>Hauptstraße</adr_strasse> + <adr_zusatz>oben links</adr_zusatz> + <adr_hausnummer>10</adr_hausnummer> + <adr_plz>24534</adr_plz> + <adr_ort>Neumünster</adr_ort> + <adr_ortsteil>Einfeld</adr_ortsteil> + <adr_land>Deutschland$DE$DEU$276$.de</adr_land> + <b_adr_numerisch>276</b_adr_numerisch> + <b_adr_land>Deutschland</b_adr_land> + <b_adr_alpha2>DE</b_adr_alpha2> + <b_adr_alpha3>DEU</b_adr_alpha3> + <b_adr_domain>.de</b_adr_domain> + <kont_telefonnummer>01234/332211</kont_telefonnummer> + <kont_telefaxnummer>01234/112233</kont_telefaxnummer> + <kont_email>${antragsteller_email}</kont_email> + <kont_demail>ea-poststelle@ea-sh.de-mail.de</kont_demail> + <kont_homepage>www.meineHomepage.de</kont_homepage> + <b_kont_vorwahl_telefon>01234</b_kont_vorwahl_telefon> + <b_kont_telefon>332211</b_kont_telefon> + <b_kont_vorwahl_telefax>01234</b_kont_vorwahl_telefax> + <b_kont_telefax>112233</b_kont_telefax> + <Status_Erlaubnis>1</Status_Erlaubnis> + <b_Erlaubnis>Liegt vor</b_Erlaubnis> + <Status_Handwerkskarte>1</Status_Handwerkskarte> + <b_Handwerkskarte>Liegt vor</b_Handwerkskarte> + <Erlaubnis> + <AusgestelltAm>2021-10-25</AusgestelltAm> + <AusgestelltVonName>Handwerkskammer</AusgestelltVonName> + <AusgestelltVonPLZ>12334</AusgestelltVonPLZ> + <AusgestelltVonOrt>Woklenkuckucksheim</AusgestelltVonOrt> + <datei_erlaubnisvorbehalt> + <datei_erlaubnisvorbehalt-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx1}" length="16242">Erlaubnis.docx</file> + </datei_erlaubnisvorbehalt-item> + </datei_erlaubnisvorbehalt> + </Erlaubnis> + <handwerkskarte> + <ausgestelltAm>2000-06-06</ausgestelltAm> + <ausgestelltVonSchluessel>00033</ausgestelltVonSchluessel> + <ausgestelltVonName>Aachen</ausgestelltVonName> + <datei_handwerkskarte> + <datei_handwerkskarte-item> + <file content-type="application/pdf" description="" id="${fileid-pdf1}" length="185763">Handwerkskarte.pdf</file> + </datei_handwerkskarte-item> + <datei_handwerkskarte-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx2}" length="16230">Handwerkskarte.docx</file> + </datei_handwerkskarte-item> + </datei_handwerkskarte> + </handwerkskarte> + </BeteiligtePerson-item> + </BeteiligtePerson> + <datei_ausweis> + <datei_ausweis-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx3}" length="16280">Anlagen2.docx</file> + </datei_ausweis-item> + <datei_ausweis-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx4}" length="16249">Anlagen.docx</file> + </datei_ausweis-item> + </datei_ausweis> + <datei_meldebestaetigung> + <datei_meldebestaetigung-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx5}" length="16273">Meldebestätigung.docx</file> + </datei_meldebestaetigung-item> + <datei_meldebestaetigung-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx6}" length="16296">Meldebestätigung2.docx</file> + </datei_meldebestaetigung-item> + </datei_meldebestaetigung> + <datei_sonstiges> + <datei_sonstiges-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx7}" length="16268">Sonstiges.docx</file> + </datei_sonstiges-item> + <datei_sonstiges-item> + <file content-type="application/vnd.openxmlformats-officedocument.wordprocessingml.document" description="" id="${fileid-docx8}" length="16292">Sonstiges2.docx</file> + </datei_sonstiges-item> + <datei_sonstiges-item> + <file content-type="application/pdf" description="" id="${fileid-pdf2}" length="187585">Anlage Vollmacht.pdf</file> + </datei_sonstiges-item> + <datei_sonstiges-item> + <file content-type="application/vnd.oasis.opendocument.text" description="" id="${fileid-odt1}" length="4799">Anlagen1.odt</file> + </datei_sonstiges-item> + <datei_sonstiges-item> + <file content-type="image/jpeg" description="" id="${fileid-jpg1}" length="10129">win.jpg</file> + </datei_sonstiges-item> + <datei_sonstiges-item> + <file content-type="image/png" description="" id="${fileid-png1}" length="50959">win.png</file> + </datei_sonstiges-item> + </datei_sonstiges> + <KontaktsystemTypA>233034600</KontaktsystemTypA> + <KontaktsystemTypB>233034601</KontaktsystemTypB> + <zustaendigestelle> + <OrganisationseinheitenAuswahl>244406514</OrganisationseinheitenAuswahl> + <OrganisationseinheitenID>${oeid}</OrganisationseinheitenID> + <OrganisationseinheitenBEZEICHNUNG>Ordnungsaufgaben, Wahlen, Gewerbeangelegenheiten der Stadt Neumünster</OrganisationseinheitenBEZEICHNUNG> + <strasse>Großflecken</strasse> + <hausnummer>63</hausnummer> + <postleitzahl>24534</postleitzahl> + <ortID>9006404</ortID> + <ort>Neumünster</ort> + <telefonnummer>+49 4321 942-0</telefonnummer> + <telefaxnummer>+49 4321 942-2521</telefaxnummer> + <emailadresse>ordnungsangelegenheiten@neumuenster.de</emailadresse> + <demailadresse/> + <AnliegenBEZEICHNUNG>Gewerbeanmeldung, Elektronische Gewerbeanzeige</AnliegenBEZEICHNUNG> + <leikaKEYLIST>99050012104000</leikaKEYLIST> + <kontaktsystem_kennung/> + <kontaktsystem_kennungzusatz/> + </zustaendigestelle> + <empfangendestelle> + <OrganisationseinheitenAuswahl>9068873</OrganisationseinheitenAuswahl> + <OrganisationseinheitenID>9068873</OrganisationseinheitenID> + <OrganisationseinheitenBEZEICHNUNG>Einheitlicher Ansprechpartner Schleswig-Holstein</OrganisationseinheitenBEZEICHNUNG> + <strasse>Reventlouallee</strasse> + <hausnummer>6</hausnummer> + <postleitzahl>24105</postleitzahl> + <ortID>9006402</ortID> + <ort>Kiel</ort> + <telefonnummer>+49 431 988-8650</telefonnummer> + <telefaxnummer>+49 431 988-6161111</telefaxnummer> + <emailadresse>info@ea-sh.de</emailadresse> + <demailadresse>ea-poststelle@ea-sh.de-mail.de</demailadresse> + <od_vorhanden>true</od_vorhanden> + <od_typid>233034600</od_typid> + <od_kennung>afmsh:9068873_AusnahmeLKWFahrverbot</od_kennung> + <od_zustellung_mail/> + <od_zustellung_nb>afmsh:9068873_AusnahmeLKWFahrverbot</od_zustellung_nb> + <od_zustellung_webservice/> + <od_kennungzusatz/> + <kontaktsystem_kennung>afmsh:9068873_AusnahmeLKWFahrverbot</kontaktsystem_kennung> + <kontaktsystem_kennungzusatz>alle</kontaktsystem_kennungzusatz> + </empfangendestelle> + <erklaerungen> + <check_gebuehren>true</check_gebuehren> + <check_richtigkeit>true</check_richtigkeit> + <check_datenschutz>true</check_datenschutz> + <check_missbrauch>true</check_missbrauch> + <check_hinweis>true</check_hinweis> + <b_gebuehren_beschriftung>* Die Gewerbeanmeldung ist kostenpflichtig. Die Höhe der Gebühren bemisst sich nach der Landesverordnung über Verwaltungsgebühren (Allgemeiner Gebührentarif) Tarifstelle 11.1.1 - VwGebV. Genaue Auskünfte hierzu erteilt das zuständige Gewerbeamt.</b_gebuehren_beschriftung> + <b_gebuehren_intro/> + <b_richtigkeit>* Ich bestätige die Richtigkeit meiner Angaben.</b_richtigkeit> + <b_datenschutz>* Ich erkläre mich damit einverstanden, dass der Einheitlicher Ansprechpartner Schleswig-Holstein zur Erfüllung seiner Aufgaben meine Daten unter Einhaltung der Bestimmungen der Datenschutz-Grundverordnung (DS-GVO) und des Landesdatenschutzgesetzes Schleswig-Holstein (LDSG-SH) speichert, verarbeitet und diese im Rahmen der gesetzlichen Bestimmungen an die für die Entscheidung zuständige Stelle weiterleitet. Ebenso bin ich mit der rechtskonformen Datenverarbeitung und Speicherung durch die zuständige Stelle einverstanden. Mir ist bekannt, dass ich die Einwilligung in die Verarbeitung und Übermittlung jederzeit gegenüber dem Einheitlicher Ansprechpartner Schleswig-Holstein, Reventlouallee 6, 24105 Kiel widerrufen kann. Ein Widerruf ist aber nur wirksam für die Zukunft. Verarbeitungen, die vor dem Widerruf erfolgt sind, sind davon nicht betroffen. Über die Verarbeitung meiner personenbezogenen Daten und die mir nach den datenschutzrechtlichen Regelungen zustehenden Ansprüche und Rechte habe ich unter Datenschutzerklärung Kenntnis erlangt.</b_datenschutz> + <b_missbrauch>* Mir ist bekannt, dass zur Verfolgung widerrechtlicher Nutzung die Daten meines zur Dateneingabe genutzten Endgerätes aufgezeichnet und verwendet werden können.</b_missbrauch> + <b_hinweis_beschriftung>* Diese Anzeige berechtigt nicht zum Beginn des Gewerbebetriebes, wenn noch eine Erlaubnis oder eine Eintragung in die Handwerksrolle notwendig ist. Zuwiderhandlungen können mit Geldbuße oder Geldstrafe oder Freiheitsstrafe geahndet werden. Diese Anzeige ist keine Genehmigung zur Errichtung einer Betriebsstätte entsprechend dem Planungs- und Baurecht.</b_hinweis_beschriftung> + <b_hinweis_intro>Hinweis</b_hinweis_intro> + <policyurl>http://wafmxqa002.dpaor.de/sh/datenschutz/datenschutzerklaerungEA_de.doc</policyurl> + </erklaerungen> + <b_timestamp>20211206093513</b_timestamp> + <logourl>http://wafmxqa002.dpaor.de/sh/logos/kopf_9068873.doc</logourl> + <fm> + <ansprechpartner> + <firmenname/> + <anrede>${antragsteller_anrede}</anrede> + <vorname>${antragsteller_vorname}</vorname> + <familienname>${antragsteller_nachname}</familienname> + <anschrift> + <strasse>Hauptstraße</strasse> + <hausnummer>10</hausnummer> + <postfach/> + <postleitzahl>24534</postleitzahl> + <ort>Neumünster</ort> + <ortsteil>Einfeld</ortsteil> + <zusatz>oben links</zusatz> + <staat>Deutschland</staat> + </anschrift> + <kontakt> + <telefonnummer>01234/332211</telefonnummer> + <mobilnummer/> + <telefaxnummer>01234/112233</telefaxnummer> + <emailadresse>${antragsteller_email}</emailadresse> + <demailadresse>ea-poststelle@ea-sh.de-mail.de</demailadresse> + </kontakt> + </ansprechpartner> + <verwaltungsleistungen> + <verwaltungsleistung> + <ausgewaehlte_zustaendigestelle> + <OrganisationseinheitenID>10363455</OrganisationseinheitenID> + <OrganisationseinheitenBEZEICHNUNG>Ordnungsaufgaben, Wahlen, Gewerbeangelegenheiten der Stadt Neumünster</OrganisationseinheitenBEZEICHNUNG> + </ausgewaehlte_zustaendigestelle> + <GebietID>9006404</GebietID> + <GebietBEZEICHNUNG>Neumünster</GebietBEZEICHNUNG> + <AnliegenID>8938634</AnliegenID> + <AnliegenBEZEICHNUNG>Gewerbeanmeldung, Elektronische Gewerbeanzeige</AnliegenBEZEICHNUNG> + <leikaKEYLIST>99050012104000</leikaKEYLIST> + <leikaBEZEICHNUNG/> + </verwaltungsleistung> + </verwaltungsleistungen> + </fm> +</myForm> diff --git a/pom.xml b/pom.xml index 251c26ae24f2f441d3981240e92df902f458fcf7..c167348631afd7ca59971fbaa037bb72b0be8222 100644 --- a/pom.xml +++ b/pom.xml @@ -31,13 +31,13 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-parent</artifactId> - <version>4.0.1</version> + <version>4.2.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>de.ozgcloud.eingang</groupId> <artifactId>eingang-manager</artifactId> - <version>2.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <packaging>pom</packaging> <name>OZG-Cloud Eingang Manager</name> diff --git a/router/pom.xml b/router/pom.xml index af606b25085e2150a860105df0b4d6c0f472dac9..0a6fa21b87e184f552accb38c7cf5d8ba70af6a5 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/run_helm_test.sh b/run_helm_test.sh index b19a9bc7c3072044dff8f0fb54c04c29acc3fbf6..ccc03d0fb89a1d2eb4c637c7d5f68ffd283051e7 100755 --- a/run_helm_test.sh +++ b/run_helm_test.sh @@ -4,4 +4,4 @@ set -e helm template ./src/main/helm/ -f src/test/helm-linter-values.yaml helm lint -f src/test/helm-linter-values.yaml ./src/main/helm/ -cd src/main/helm && helm unittest -f '../../test/helm/**/*test.yaml' . \ No newline at end of file +cd src/main/helm && helm unittest -f '../../test/helm/**/*.yaml' . \ No newline at end of file diff --git a/semantik-adapter/pom.xml b/semantik-adapter/pom.xml index ca5cde0556e7dccac70388701cc2fb40ed46c636..d28c38abf7daa861cd35148a8c7e730a288c7c52 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.8.0-SNAPSHOT</version> + <version>2.10.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 74840e2f51139b08cf49bb19bb7016a71dfa2bd9..47a3d8570d4b2b6c3b3b7aaa5a5d2bba58271f57 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 @@ -23,7 +23,7 @@ */ package de.ozgcloud.eingang.semantik; -import java.util.Objects; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -36,11 +36,10 @@ import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter; @Service public class SemantikAdapter { - @Autowired(required = false) - private EngineBasedSemantikAdapter engineBasedAdapter; + @Autowired + private List<EngineBasedSemantikAdapter> engineBasedAdapters; @Autowired private FormBasedSemantikAdapter formBasedAdapter; - @Autowired private VorgangService vorgangService; @@ -52,13 +51,19 @@ public class SemantikAdapter { } private FormData parseByEngineAdapter(FormData formData) { - if (Objects.nonNull(engineBasedAdapter)) { - return engineBasedAdapter.parseFormData(formData); + for (var adapter : getResponsibleEngineAdapters(formData)) { + formData = adapter.parseFormData(formData); } return formData; } + List<EngineBasedSemantikAdapter> getResponsibleEngineAdapters(FormData formData) { + return engineBasedAdapters.stream() + .filter(adapter -> adapter.isResponsible(formData)) + .toList(); + } + private FormData parseByFormAdapter(FormData formData) { return formBasedAdapter.parseFormData(formData); } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactory.java similarity index 71% rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelper.java rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactory.java index 1ec87a0e456865b00b7edbddf0834dad0f8e9948..0b7320fbe23a0a9820ccebfa9c82fd78347798f4 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactory.java @@ -1,4 +1,4 @@ -package de.ozgcloud.eingang.semantik.enginebased; +package de.ozgcloud.eingang.semantik.common; import java.util.Collections; import java.util.List; @@ -6,21 +6,27 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import org.apache.commons.collections.MapUtils; import org.springframework.stereotype.Component; import de.ozgcloud.eingang.common.formdata.FormData; 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.eingang.common.formdata.ServiceKonto.TrustLevel; +import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier; +import lombok.extern.log4j.Log4j2; @Component -public class ServiceKontoBuildHelper { +@Log4j2 +public class ServiceKontoFactory { public static final int POSTFACH_ADDRESS_DEFAULT = 1; public static final String POSTFACH_TYPE_OSI = "OSI"; public static final String POSTFACH_TYPE_BAYERN_ID = "BayernID"; public static final String POSTFACH_VERSION = "1.0"; + public static final String KEY_BAYERN_ID_POSTFACH_ID = "u:saml_legacypostkorbhandle"; + public static final String KEY_BAYERN_ID_TRUST_LEVEL = "u:saml_eid_citizen_qaa_level"; public static final String REST_RESPONSE_NAME = "rest_response_name"; public static final String REST_RESPONSE_NAME_MEMBER_SCOPE = "memberscope"; @@ -85,8 +91,27 @@ public class ServiceKontoBuildHelper { return ((List<Map<String, Object>>) restResponseName.get(REST_RESPONSE_NAME_MEMBER_SCOPE)).get(0); } - public ServiceKonto buildBayernIdServiceKonto(String postfachId) { - return ServiceKonto.builder().type(POSTFACH_TYPE_BAYERN_ID).postfachAddress(buildPostfachAddress(postfachId)).build(); + public Optional<ServiceKonto> createBayernIdServiceKonto(Map<String, Object> formDataHeaders) { + if (Objects.isNull(formDataHeaders) || !formDataHeaders.containsKey(KEY_BAYERN_ID_POSTFACH_ID)) { + return Optional.empty(); + } + if (isValidTrustLevel(formDataHeaders)) { + return Optional.of(buildBayernIdServiceKonto(formDataHeaders)); + } + LOG.error("TrustLevel has an unexpected value '{}'. BayernID user account is not connected", getTrustLevel(formDataHeaders)); + return Optional.empty(); + } + + boolean isValidTrustLevel(Map<String, Object> formDataHeader) { + return TrustLevel.exists(getTrustLevel(formDataHeader)); + } + + ServiceKonto buildBayernIdServiceKonto(Map<String, Object> formDataHeaders) { + return ServiceKonto.builder() + .type(POSTFACH_TYPE_BAYERN_ID) + .postfachAddress(buildPostfachAddress(MapUtils.getString(formDataHeaders, KEY_BAYERN_ID_POSTFACH_ID))) + .trustLevel(getTrustLevel(formDataHeaders)) + .build(); } PostfachAddress buildPostfachAddress(String postkorbHandle) { @@ -101,4 +126,8 @@ public class ServiceKontoBuildHelper { return StringBasedIdentifier.builder().postfachId(postfachId).build(); } + String getTrustLevel(Map<String, Object> formDataHeaders) { + return MapUtils.getString(formDataHeaders, KEY_BAYERN_ID_TRUST_LEVEL); + } + } \ No newline at end of file diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java index 866b8fc52a49b92460625922df950f46224a6043..9679dc725335d8c95f9e7e1114c7c0a5d48f22ce 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java @@ -28,4 +28,9 @@ import de.ozgcloud.eingang.common.formdata.FormData; public interface EngineBasedSemantikAdapter { FormData parseFormData(FormData formData); + + // TODO Umbauen zu `public String[] getFormEngines();` + default boolean isResponsible(FormData formData) { + return true; + } } diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12Eingang.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12Eingang.java new file mode 100644 index 0000000000000000000000000000000000000000..c9f93b0c0196b2bf9d97ff98043b48b04943de94 --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12Eingang.java @@ -0,0 +1,15 @@ +package de.ozgcloud.eingang.semantik.enginebased.a12; + +import java.util.Map; + +import lombok.Builder; +import lombok.Getter; +import lombok.extern.jackson.Jacksonized; + +@Builder +@Getter +@Jacksonized +public class A12Eingang { + + private Map<String, Object> root; +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12EngineBasedAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12EngineBasedAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..ac42d7f7cfa1c7cdf7ded2fcac816cda943e42cc --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12EngineBasedAdapter.java @@ -0,0 +1,24 @@ +package de.ozgcloud.eingang.semantik.enginebased.a12; + +import java.util.List; + +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class A12EngineBasedAdapter implements EngineBasedSemantikAdapter { + + private final List<A12EngineBasedMapper> mappers; + + @Override + public FormData parseFormData(FormData formData) { + var processedFormData = formData; + + for (var mapper : mappers) { + processedFormData = mapper.parseFormData(processedFormData); + } + return processedFormData; + } + +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12EngineBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12EngineBasedMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3f441525324679a29fc4adc0bec2574ef7b3df7a --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12EngineBasedMapper.java @@ -0,0 +1,7 @@ +package de.ozgcloud.eingang.semantik.enginebased.a12; + +import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper; + +public interface A12EngineBasedMapper extends EngineBasedMapper { + +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12FormDataMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12FormDataMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..688726362cc93f2b271f683f28ad7a929f725432 --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12FormDataMapper.java @@ -0,0 +1,79 @@ +package de.ozgcloud.eingang.semantik.enginebased.a12; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormData.FormDataControl; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Component +@RequiredArgsConstructor +public class A12FormDataMapper implements A12EngineBasedMapper { + + private final ObjectMapper objectMapper; + + @Override + public FormData parseFormData(FormData formData) { + return mergeReadFormData(formData, getFormDataFile(formData)); + } + + private FormData mergeReadFormData(FormData formData, Optional<IncomingFile> inFile) { + return inFile.map(in -> readEingang(in.getFile())) + .map(eingang -> eingang.getRoot()) + .map(formDataMap -> merge(formDataMap, formData.getFormData())) + .map(formDataMap -> formData.toBuilder().formData(formDataMap).build()) + .orElse(formData); + } + + Optional<IncomingFile> getFormDataFile(FormData formData) { + var inFile = Optional.ofNullable(formData.getControl()) + .flatMap(FormDataControl::getRepresentations) + .map(Representations::getPrimaryFormDataRepresentation) + .flatMap(fileName -> getByName(fileName, formData.getRepresentations())); + + logWarnIfEmpty(inFile); + return inFile; + } + + A12Eingang readEingang(File formDataJson) { + try { + return objectMapper.readValue(formDataJson, A12Eingang.class); + } catch (IOException e) { + throw new TechnicalException("Error parsing JSON from A12 FormDataFile", e); + } + } + + void logWarnIfEmpty(Optional<IncomingFile> inFile) { + if (inFile.isEmpty()) { + LOG.warn("No primary Form Data Representation found."); + } + } + + Optional<IncomingFile> getByName(String name, List<IncomingFile> inFiles) { + return inFiles.stream() + .filter(inFile -> StringUtils.equals(name, inFile.getName())) + .findFirst(); + } + + <A, B> Map<A, B> merge(Map<A, B> map1, Map<A, B> map2) { + var map = new HashMap<>(map1); + map.putAll(map2); + return Collections.unmodifiableMap(map); + } +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java index 3171846b129f4f676a7392d2f857e0f72714705c..df134be93dbf148d8cc9f2009d9f2ad6ec6d581d 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java @@ -6,16 +6,17 @@ import static org.apache.commons.lang3.StringUtils.*; import java.util.Collections; import java.util.Map; +import org.apache.commons.collections.MapUtils; import org.springframework.stereotype.Component; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.Antragsteller; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; @Component public class AfmAntragstellerHeaderMapper { - static final String KEY_POSTFACH_ID = "u:saml_legacypostkorbhandle"; static final String KEY_VORNAME = "u:saml_givenname"; static final String KEY_NACHNAME = "u:saml_surname"; static final String KEY_GEBURTSORT = "u:saml_placeofbirth"; @@ -32,22 +33,23 @@ public class AfmAntragstellerHeaderMapper { Antragsteller buildAntragsteller(Map<String, Object> headers) { return Antragsteller.builder() - .postfachId((String) headers.get(KEY_POSTFACH_ID)) - .vorname((String) headers.get(KEY_VORNAME)) - .nachname((String) headers.get(KEY_NACHNAME)) - .geburtsname((String) headers.get(KEY_GEBURTSNAME)) - .geburtsort((String) headers.get(KEY_GEBURTSORT)) - .email((String) headers.get(KEY_EMAIL)) - .telefon((String) headers.get(KEY_TELEFON)) - .strasse((String) headers.get(KEY_STRASSE)) - .plz((String) headers.get(KEY_PLZ)) - .ort((String) headers.get(KEY_ORT)) + .postfachId(MapUtils.getString(headers, ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID)) + .vorname(MapUtils.getString(headers, KEY_VORNAME)) + .nachname(MapUtils.getString(headers, KEY_NACHNAME)) + .geburtsname(MapUtils.getString(headers, KEY_GEBURTSNAME)) + .geburtsort(MapUtils.getString(headers, KEY_GEBURTSORT)) + .email(MapUtils.getString(headers, KEY_EMAIL)) + .telefon(MapUtils.getString(headers, KEY_TELEFON)) + .strasse(MapUtils.getString(headers, KEY_STRASSE)) + .plz(MapUtils.getString(headers, KEY_PLZ)) + .ort(MapUtils.getString(headers, KEY_ORT)) .build(); } public boolean isResponsible(FormData formData) { var headers = getHeaders(formData); - return headers.containsKey(KEY_POSTFACH_ID) && isPostfachIdNotBlank(headers.get(KEY_POSTFACH_ID)); + return headers.containsKey(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID) + && isPostfachIdNotBlank(headers.get(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID)); } @SuppressWarnings("unchecked") diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java index ac02afebba1744dce9c70987997fd397fb4ea601..52365312ec979e24d37560740ce9fca8c02db523 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java @@ -95,7 +95,8 @@ class AfmAntragstellerMapper implements AfmEngineBasedMapper { private Optional<Map<String, Object>> getAntragstellerMap(Map<String, Object> formDataMap) { return Optional.ofNullable(formDataMap.get(ANTRAGSTELLER)) .or(() -> Optional.ofNullable(formDataMap.get(ANTRAGSTELLER_UPPERCASE))) - .map(Map.class::cast).map(LinkedHashMap<String, Object>::new); + .map(Map.class::cast) + .map(LinkedHashMap<String, Object>::new); } private Antragsteller.AntragstellerBuilder addAntragstellerData(Antragsteller.AntragstellerBuilder builder, @@ -162,4 +163,4 @@ class AfmAntragstellerMapper implements AfmEngineBasedMapper { } return Collections.unmodifiableMap(editableMap); } -} \ No newline at end of file +} 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 739ef9e7c9fe38bdede62e9812ec9a98821f7297..5d7224c75ce7ff634737b79d28aeaf6e05931c6d 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 @@ -23,33 +23,53 @@ */ package de.ozgcloud.eingang.semantik.enginebased.afm; -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; - import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataUtils; import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; +import de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.IntelliFormRepresentationAdapter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +@Component public class AfmEngineBasedAdapter implements EngineBasedSemantikAdapter { + @Autowired + private IntelliFormRepresentationAdapter intelliFormRepresentationAdapter; + @Autowired private List<AfmEngineBasedMapper> mappers; @Override public FormData parseFormData(FormData formData) { - var processedFormData = formData; + var vorgangNummer = formData.getHeader().getVorgangNummer(); + var processedFormData = intelliFormRepresentationAdapter.adaptByRepresentations(formData); for (var mapper : mappers) { processedFormData = mapper.parseFormData(processedFormData); } - return removeProcessedData(processedFormData); + return removeProcessedData(addVorgangNummer(processedFormData, vorgangNummer)); + } + + private FormData addVorgangNummer(FormData formData, String vorgangNummer) { + return formData.toBuilder() + .header(formData.getHeader().toBuilder() + .vorgangNummer(vorgangNummer) + .build() + ) + .build(); } - FormData removeProcessedData(FormData formData) { + private FormData removeProcessedData(FormData formData) { return FormDataUtils.from(formData) .remove(AfmAntragstellerMapper.POSTFACH_ID) .build(); } -} \ No newline at end of file + + @Override + public boolean isResponsible(FormData formData) { + return intelliFormRepresentationAdapter.isResponsible(formData); + } +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapper.java similarity index 68% rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapper.java rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapper.java index 6daeceab9dfd7e9f397b46fa087792ae4dff7560..e706d63e31d8161b639826fe9f22b06beeda65d1 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapper.java @@ -29,19 +29,14 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper; @Component -class AfmAttachedFilesMapper implements AfmEngineBasedMapper { +class AfmFileCountMapper implements AfmEngineBasedMapper { @Override public FormData parseFormData(FormData formData) { - var formDataBuilder = formData.toBuilder(); - FilesMapperHelper.getAttachedFileGroups(formData) - .ifPresent(fileGroups -> formDataBuilder - .attachments(fileGroups) - .numberOfAttachments(FilesMapperHelper.countAttachedFiles(fileGroups))); - FilesMapperHelper.getRepresentations(formData) - .ifPresent(representations -> formDataBuilder.representations(representations).numberOfRepresentations(representations.size())); - - return FilesMapperHelper.removeProcessedData(formDataBuilder.build()); + return formData.toBuilder() + .numberOfRepresentations(formData.getRepresentations().size()) + .numberOfAttachments(FilesMapperHelper.countAttachedFiles(formData.getAttachments())) + .build(); } -} \ No newline at end of file +} 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 2984f9a6d257eeae0e1c6e2d361383b37d6a2dbb..0f63ef3686963482d332dd1d844e75ae4d2ec865 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 @@ -35,7 +35,7 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataUtils; import de.ozgcloud.eingang.common.formdata.FormHeader; import de.ozgcloud.eingang.common.formdata.ServiceKonto; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; @Component class AfmHeaderMapper implements AfmEngineBasedMapper { @@ -53,7 +53,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper { static final String SENDER = "t:sender"; @Autowired - private ServiceKontoBuildHelper serviceKontoBuildHelper; + private ServiceKontoFactory serviceKontoFactory; @Override public FormData parseFormData(FormData formData) { @@ -84,13 +84,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper { } Optional<ServiceKonto> createBayernIdServiceKonto(FormData formData) { - var postfachId1 = getPostfachId(formData); - return postfachId1.map(postfachId -> serviceKontoBuildHelper.buildBayernIdServiceKonto(postfachId)); - } - - Optional<String> getPostfachId(FormData formData) { - return Optional.ofNullable(getHeaderMap(formData)).map(headers -> headers.get(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID)) - .map(String.class::cast); + return serviceKontoFactory.createBayernIdServiceKonto(getHeaderMap(formData)); } @SuppressWarnings("unchecked") @@ -99,7 +93,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper { } Optional<ServiceKonto> createOsiServiceKonto(FormData formData) { - return getNameId(formData).map(nameId -> serviceKontoBuildHelper.buildOsiServiceKonto(nameId, formData)); + return getNameId(formData).map(nameId -> serviceKontoFactory.buildOsiServiceKonto(nameId, formData)); } private Optional<String> getNameId(FormData formData) { @@ -108,7 +102,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper { private FormData removeMappedData(FormData formData) { return FormDataUtils.from(formData) - .remove(ServiceKontoBuildHelper.REST_RESPONSE_NAME) + .remove(ServiceKontoFactory.REST_RESPONSE_NAME) .build(); } } \ No newline at end of file diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..d96052447475590512a9ac5cd2280ebe22d0715f --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java @@ -0,0 +1,145 @@ +package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.collections.MapUtils; +import org.springframework.stereotype.Component; +import org.w3c.dom.Document; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Component +@RequiredArgsConstructor +@Log4j2 +public class IntelliFormRepresentationAdapter { + + static final String INTELLIFORM_TYPENAME = "http://xmlns.cit.de/intelliform/transaction"; + + static final String FILE = "file"; + + static final String HEADER_FIELD = "header"; + + public static final List<String> HEADER_ATTRIBUTE_NAMES = List.of( + "t:id", + "t:timestamp", + "t:form-id", + "t:form", + "t:sender", + "t:customer", + "t:customer-id", + "t:client", + "t:client-id" + ); + public static final List<String> CUSTOM_HEADER_ATTRIBUTE_NAMES = List.of( + "u:saml_legacypostkorbhandle", + "u:saml_givenname", + "u:saml_surname", + "u:saml_placeofbirth", + "u:saml_birthname", + "u:saml_mail", + "u:saml_telephonenumber", + "u:saml_postaladdress", + "u:saml_postalcode", + "u:saml_localityname", + ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL + ); + + private static final Collector<Map.Entry<String, ?>, ?, Map<String, Object>> ORDERED_MAP_ENTRY_COLLECTOR = Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (u, v) -> v, + LinkedHashMap::new + ); + + private final XmlToJavaMapsMapper xmlToJavaMapsMapper; + + public boolean isResponsible(FormData formData) { + return findIntelliFormXMLRepresentation(formData) + .isPresent(); + } + + Optional<Document> findIntelliFormXMLRepresentation(FormData formData) { + return streamXMLDocumentsFromRepresentations(formData) + .filter(document -> { + var element = document.getDocumentElement(); + var attribute = element.getAttribute("xmlns:t"); + return attribute.equals(INTELLIFORM_TYPENAME); + }) + .findFirst(); + } + + Stream<Document> streamXMLDocumentsFromRepresentations(FormData formData) { + return formData.getRepresentations().stream() + .filter(representation -> representation.getContentType().contains("xml")) + .flatMap(xmlRepresentation -> { + try { + return Stream.of(xmlToJavaMapsMapper.parseAsW3cDocument(xmlRepresentation.getContentStream())); + } catch (TechnicalException exception) { + return Stream.empty(); + } + }); + } + + public FormData adaptByRepresentations(FormData formData) { + var document = findIntelliFormXMLRepresentation(formData) + .orElseThrow(() -> new TechnicalException("Expect to find IntelliForm XML representation!")); + + return FormData.builder() + .representations(formData.getRepresentations()) + .attachments(formData.getAttachments()) + .formData(Stream.concat( + getFormDataEntriesFromDocument(document, formData.getAttachments()), + Map.of( + HEADER_FIELD, createHeaderMap(document) + ).entrySet().stream() + ).collect(ORDERED_MAP_ENTRY_COLLECTOR)) + .build(); + } + + Stream<Map.Entry<String, Object>> getFormDataEntriesFromDocument(Document document, List<IncomingFileGroup> attachments) { + Set<String> attachmentVendorIds = attachments.stream() + .flatMap(group -> group.getFiles().stream()) + .map(IncomingFile::getVendorId) + .collect(Collectors.toSet()); + + return xmlToJavaMapsMapper.mapXmlToJavaMaps(document).entrySet() + .stream() + .filter(entry -> !isUploadElementWhichRefersToAttachment(entry.getValue(), attachmentVendorIds)); + } + + private boolean isUploadElementWhichRefersToAttachment(Object element, Set<String> attachmentVendorIds) { + return findVendorIdInUploadElementCandidate(element) + .map(attachmentVendorIds::contains) + .orElse(false); + } + + @SuppressWarnings("rawtypes") + private Optional<String> findVendorIdInUploadElementCandidate(Object element) { + if (element instanceof Map uploadElement) { + return Optional.ofNullable(MapUtils.getMap(uploadElement, FILE)) + .flatMap(fileElement -> Optional.ofNullable(MapUtils.getString(fileElement, "id"))); + } else { + return Optional.empty(); + } + } + + Map<String, Object> createHeaderMap(Document document) { + var element = document.getDocumentElement(); + return Stream.concat(HEADER_ATTRIBUTE_NAMES.stream(), CUSTOM_HEADER_ATTRIBUTE_NAMES.stream().filter(element::hasAttribute)) + .collect(Collectors.toMap(name -> name, element::getAttribute)); + } + +} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/JsonService.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonService.java similarity index 93% rename from intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/JsonService.java rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonService.java index fa8c516f641b18f518ec3d19323a01d81a7287c4..04d21f1a271da454917f3a580727e31bc3baac98 100644 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/JsonService.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonService.java @@ -1,4 +1,4 @@ -package de.ozgcloud.eingang.intelliform; +package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform; import java.util.List; import java.util.Map; @@ -32,4 +32,4 @@ class JsonService { throw new TechnicalException("Error parsing JSON", e); } } -} \ No newline at end of file +} diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapper.java similarity index 98% rename from intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapper.java rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapper.java index bd7164616db3a639cfe66538da9beafd303aaabf..75409a60e28a1966f85e4b1caa4ecdda90fa569e 100644 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapper.java @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.eingang.intelliform; +package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform; import java.io.IOException; import java.io.InputStream; @@ -184,4 +184,4 @@ class XmlToJavaMapsMapper { return Collections.emptyList(); } } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapter.java similarity index 79% rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapper.java rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapter.java index 6c2292d48b4b596feef5e0abdc3d087099a94d9d..b3e75f0cd900dd24d9095c7953939ae450d5db5c 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapter.java @@ -1,4 +1,4 @@ -package de.ozgcloud.eingang.semantik.formbased; +package de.ozgcloud.eingang.semantik.enginebased.dfoerdermittel; import java.io.IOException; import java.io.InputStream; @@ -20,13 +20,14 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.common.formdata.ServiceKonto; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; import lombok.NonNull; import lombok.extern.log4j.Log4j2; @Log4j2 @Component -public class DFoerdermittelFormBasedMapper implements FormBasedMapper { +public class DFoerdermittelEngineBasedSemantikAdapter implements EngineBasedSemantikAdapter { private static final String FACHNACHRICHT_SUFFIX = "Fachnachricht.xml"; private static final Predicate<IncomingFile> IS_FACHNACHRICHT = inFile -> StringUtils.endsWith(inFile.getName(), FACHNACHRICHT_SUFFIX); @@ -36,7 +37,7 @@ public class DFoerdermittelFormBasedMapper implements FormBasedMapper { private static final String KEY_ORGANISATIONS_EINHEIT_ID = "MetaText1"; @Autowired - private ServiceKontoBuildHelper serviceKontoHelper; + private ServiceKontoFactory serviceKontoFactory; @Override public FormData parseFormData(FormData formData) { @@ -51,7 +52,9 @@ public class DFoerdermittelFormBasedMapper implements FormBasedMapper { Map<String, Object> fachnachricht = (Map<String, Object>) MapUtils.getMap(formData.getFormData(), KEY_FACHNACHRICHT, Collections.<String, Object>emptyMap()); - var extendedFormData = addServiceKonto(formData, fachnachricht); + var extendedFormData = addFormName(formData); + extendedFormData = addFormEngineName(extendedFormData); + extendedFormData = addServiceKonto(extendedFormData, fachnachricht); return addOrganisationsEinheitId(extendedFormData, fachnachricht); } @@ -82,12 +85,31 @@ public class DFoerdermittelFormBasedMapper implements FormBasedMapper { return zustaendigeStelleBuilder.organisationseinheitenId(orgaId).build(); } + FormData addFormName(FormData formData) { + return formData.toBuilder() + .header(formData.getHeader().toBuilder() + // TODO replace formName with actual name <Title> from Fachnachricht (KOP-2239) + .formName("dFördermittelantrag") + .build() + ) + .build(); + } + + FormData addFormEngineName(FormData formData) { + return formData.toBuilder() + .header(formData.getHeader().toBuilder() + .formEngineName("dFördermittelantrag") + .build() + ) + .build(); + } + String extractPrefix(@NonNull String postfachId) { return postfachId.substring(postfachId.lastIndexOf("/") + 1); } private ServiceKonto createServiceKonto(String postfachId) { - return serviceKontoHelper.buildOsiServiceKonto(postfachId); + return serviceKontoFactory.buildOsiServiceKonto(postfachId); } FormData parseFachnachricht(FormData formData, IncomingFile fachnachrichtFile) { diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java index f4e91092747456556d75874ee1a8cddc12c5dfc2..6de90deb9ebc890fba588b4f4ea60c983804c300 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java @@ -110,4 +110,4 @@ class FormSolutionsFilesMapper implements FormSolutionsEngineBasedMapper { return ZipAttachmentReader.from(zipFile.getFile(), zipFile.getName()); } } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java index 0c8bc2d63bcbf51bdfba7f6963cac424c773c7e8..c2b0de118717b7bb54f0af27ef37e123788f3368 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java @@ -34,7 +34,7 @@ import org.springframework.stereotype.Component; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataUtils; import de.ozgcloud.eingang.common.formdata.FormHeader; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; @Component class FormSolutionsHeaderMapper implements FormSolutionsEngineBasedMapper { @@ -48,7 +48,7 @@ class FormSolutionsHeaderMapper implements FormSolutionsEngineBasedMapper { public static final String POSTKORBHANDLE = "postkorbhandle"; @Autowired - private ServiceKontoBuildHelper serviceKontoBuildHelper; + private ServiceKontoFactory serviceKontoFactory; @Override public FormData parseFormData(FormData formData) { @@ -66,7 +66,7 @@ class FormSolutionsHeaderMapper implements FormSolutionsEngineBasedMapper { .requestId(getRequestId(formData)) .formEngineName(FORM_ENGINE_NAME); - Optional.ofNullable(getPostkorbhandle(formData)).map(serviceKontoBuildHelper::buildOsiServiceKonto).ifPresent(formHeaderBuilder::serviceKonto); + Optional.ofNullable(getPostkorbhandle(formData)).map(serviceKontoFactory::buildOsiServiceKonto).ifPresent(formHeaderBuilder::serviceKonto); return formHeaderBuilder.build(); } diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedAdapter.java deleted file mode 100644 index a74ff267bd5984e068abd0fc00a9bd6c2469e05d..0000000000000000000000000000000000000000 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedAdapter.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.ozgcloud.eingang.semantik.enginebased.xta; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; - -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; - -public class XtaEngineBasedAdapter implements EngineBasedSemantikAdapter { - - @Autowired - private List<XtaEngineBasedMapper> mappers; - - @Override - public FormData parseFormData(FormData formData) { - var processed = formData; - - for (var mapper : mappers) { - processed = mapper.parseFormData(processed); - } - - return processed; - } - -} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedMapper.java deleted file mode 100644 index 085f7f230d0b65cd06215654e1554c31cce7baeb..0000000000000000000000000000000000000000 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedMapper.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.ozgcloud.eingang.semantik.enginebased.xta; - -import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper; - -public interface XtaEngineBasedMapper extends EngineBasedMapper { - -} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapper.java deleted file mode 100644 index 9a0814f1efa9b86843d27db360a53986091b2dd2..0000000000000000000000000000000000000000 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapper.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.ozgcloud.eingang.semantik.enginebased.xta; - -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.stereotype.Component; - -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.semantik.common.ZipAttachmentReader; -import lombok.extern.log4j.Log4j2; - -@Component -@Log4j2 -public class XtaZipRepresentationsMapper implements XtaEngineBasedMapper { - - public static final String ZIP_CONTENT_TYPE = "application/zip"; - - static final Predicate<IncomingFile> IS_ZIP_FILE = contentType -> ZIP_CONTENT_TYPE.equals(contentType.getContentType()); - - @Override - public FormData parseFormData(FormData srcFormData) { - - List<IncomingFile> extractedFiles = srcFormData.getRepresentations().stream() - .filter(IS_ZIP_FILE) - .map(this::extractZip) - .flatMap(List::stream) - .toList(); - - return srcFormData - .toBuilder() - .representations(extractedFiles) - .numberOfRepresentations(srcFormData.getNumberOfRepresentations() + extractedFiles.size()).build(); - } - - List<IncomingFile> extractZip(IncomingFile zipFile) { - try { - return ZipAttachmentReader.from(zipFile.getContentStream(), zipFile.getName()).readContent(); - } catch (RuntimeException e) { - LOG.error("Cannot read source ZIP. Not extracting file", e); - return Collections.emptyList(); - } - } -} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java index c234ffb21472a2cba5a430312eab492b72982e43..47e053f919675dbbf0f1ab139117ceb65b210193 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java @@ -25,7 +25,7 @@ package de.ozgcloud.eingang.semantik.formbased; import de.ozgcloud.eingang.common.formdata.FormData; -interface FormBasedMapper { +public interface FormBasedMapper { FormData parseFormData(FormData formData); diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java index 823879bd947e3526e7931808bfdbc9b62749264e..9f2d644ab509c5cfce07cca94a33c1b8abefa2ed 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java @@ -60,4 +60,4 @@ public class FormBasedSemantikAdapter { } -} \ 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 new file mode 100644 index 0000000000000000000000000000000000000000..9ddc1287c6c7433070c59de09264b0f8156bcc75 --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java @@ -0,0 +1,109 @@ +package de.ozgcloud.eingang.semantik.formbased.mantelantrag; + +import java.util.Map; +import java.util.Optional; +import java.util.function.UnaryOperator; +import java.util.stream.IntStream; + +import org.apache.commons.collections.MapUtils; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormHeader; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import de.ozgcloud.eingang.semantik.formbased.FormBasedMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Component +@RequiredArgsConstructor +@Log4j2 +public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { + static final String MANTELANTRAG_FORM_ID = "maa_mantelantrag/maa_mantelantrag"; + static final String ZUSTELLUNG_NACHRICHTENBROKER_FIELD = "zustellung_nachrichtenbroker"; + static final String ORGANISATIONSEINHEIT_ID_FIELD = "kontaktsystem_oeid"; + static final String BEZEICHNUNG_FIELD = "OrganisationseinheitenBEZEICHNUNG"; + static final String EMAIL_FIELD = "zust_emailadresse"; + static final String HAUSANSCHRIFT_STRASSE_FIELD = "zust_strasse"; + static final String HAUSANSCHRIFT_PLZ_FIELD = "zust_postleitzahl"; + static final String HAUSANSCHRIFT_ORT_FIELD = "zust_ort"; + static final String TELEFON_FIELD = "telefon"; + + private final Environment environment; + + @Override + public boolean isResponsible(FormData formData) { + return Optional.ofNullable(formData.getHeader()) + .map(FormHeader::getFormId) + .map(v -> v.startsWith(MANTELANTRAG_FORM_ID)) + .orElse(false); + } + + @Override + public FormData parseFormData(FormData formData) { + try { + return adaptFormDataWithPossibleException(formData); + } catch (TechnicalException exception) { + LOG.warn("Mantelantrag is invalid: %s".formatted(exception.getMessage())); + return formData; + } + } + + FormData adaptFormDataWithPossibleException(FormData formData) { + var fieldMap = formData.getFormData(); + var slotIndex = findSlotIndex(fieldMap); + return adaptFormDataWithValueGetter(formData, field -> getFieldByKeyOrEmpty( + fieldMap, + getNameForSlotIndex(field, slotIndex) + )); + } + + private FormData adaptFormDataWithValueGetter(FormData formData, UnaryOperator<String> getValueOrEmpty) { + return formData.toBuilder() + .zustaendigeStelle(ZustaendigeStelle.builder() + .organisationseinheitenId(getOrganisationseinheitId(getValueOrEmpty)) + .bezeichnung(getValueOrEmpty.apply(BEZEICHNUNG_FIELD)) + .email(getValueOrEmpty.apply(EMAIL_FIELD)) + .hausanschriftStrasse(getValueOrEmpty.apply(HAUSANSCHRIFT_STRASSE_FIELD)) + .hausanschriftPlz(getValueOrEmpty.apply(HAUSANSCHRIFT_PLZ_FIELD)) + .hausanschriftOrt(getValueOrEmpty.apply(HAUSANSCHRIFT_ORT_FIELD)) + .telefon(getValueOrEmpty.apply(TELEFON_FIELD)) + .build()) + .build(); + } + + private String getOrganisationseinheitId(UnaryOperator<String> getValueOrEmpty) { + var organisationseinheitId = getValueOrEmpty.apply(ORGANISATIONSEINHEIT_ID_FIELD); + + if (organisationseinheitId.isBlank()) { + throw new TechnicalException("OrganistaionseinheitId not found!"); + } + + return organisationseinheitId; + } + + int findSlotIndex(Map<String, Object> fieldMap) { + var identifier = environment.getProperty("ozgcloud.xta.identifier"); + 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))); + } + + String getNameForSlotIndex(String name, int slotIndex) { + return slotIndex > 0 ? "%s%d".formatted(name, slotIndex + 1) : name; + } + + private String getFieldByKeyOrEmpty(Map<String, Object> fieldMap, String key) { + return Optional.ofNullable(MapUtils.getString(fieldMap, key)) + .map(String::trim) + .orElse(""); + } + +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java index 98b3e7fc66f6f4a1ccd849a07c68cc0e6eed9755..754667f0298c9d867846cafee6f28d6b82677fd2 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java @@ -23,25 +23,35 @@ */ package de.ozgcloud.eingang.semantik; +import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.List; +import java.util.stream.Stream; + 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; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.router.VorgangService; -import de.ozgcloud.eingang.semantik.SemantikAdapter; import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter; class SemantikAdapterTest { + @Spy @InjectMocks private SemantikAdapter adapter; + + @Mock + private List<EngineBasedSemantikAdapter> engineAdapters; + @Mock private EngineBasedSemantikAdapter engineAdapter; @Mock @@ -49,6 +59,30 @@ class SemantikAdapterTest { @Mock private VorgangService vorgangService; + @DisplayName("get responsible engine adapters") + @Nested + class TestGetResponsibleEngineAdapters { + @Mock + private EngineBasedSemantikAdapter unresponsibleEngineAdapter; + @Mock + private FormData formData; + + @BeforeEach + void mock() { + when(unresponsibleEngineAdapter.isResponsible(formData)).thenReturn(false); + when(engineAdapter.isResponsible(formData)).thenReturn(true); + when(engineAdapters.stream()).thenReturn(Stream.of(engineAdapter, unresponsibleEngineAdapter)); + } + + @DisplayName("should return responsible") + @Test + void shouldReturnResponsible() { + var foundAdapters = adapter.getResponsibleEngineAdapters(formData); + + assertThat(foundAdapters).isEqualTo(List.of(engineAdapter)); + } + } + @Nested class TestProcessFormData { @@ -61,10 +95,18 @@ class SemantikAdapterTest { @BeforeEach void mockEngineAdapter() { + doReturn(List.of(engineAdapter)).when(adapter).getResponsibleEngineAdapters(formData); when(engineAdapter.parseFormData(any())).thenReturn(engineAdapterResponse); when(formAdapter.parseFormData(any())).thenReturn(formAdapterResponse); } + @Test + void shouldCallFindEngineAdapter() { + adapter.processFormData(formData); + + verify(adapter).getResponsibleEngineAdapters(formData); + } + @Test void shouldCallEngineAdapter() { adapter.processFormData(formData); @@ -86,4 +128,4 @@ class SemantikAdapterTest { verify(vorgangService).createVorgang(formAdapterResponse); } } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactoryTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..66d9d3e302806e9b4aab54e4bba79627488e92fe --- /dev/null +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactoryTest.java @@ -0,0 +1,303 @@ +package de.ozgcloud.eingang.semantik.common; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.Map; + +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.Spy; + +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormDataUtils; +import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; +import de.ozgcloud.eingang.common.formdata.ServiceKonto; +import de.ozgcloud.eingang.common.formdata.ServiceKonto.TrustLevel; +import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; +import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier; +import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress; +import de.ozgcloud.eingang.semantik.enginebased.afm.AfmHeaderTestFactory; + +class ServiceKontoFactoryTest { + + @Spy + @InjectMocks + private ServiceKontoFactory factory; + + @DisplayName("OSI service konto") + @Nested + class TestOsiServiceKonto { + + private static final FormData FORM_DATA = FormData.builder().formData(AfmHeaderTestFactory.createFormDataMap()).build(); + + @DisplayName("with configured postfach") + @Nested + class TestWithConfiguredPostfach { + + private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create(); + + @BeforeEach + void mockBuildPostfachAddresses() { + doReturn(List.of(POSTFACH_ADDRESS)).when(factory).buildPostfachAddresses(any(), any()); + } + + @Test + void shouldContainsType() { + var serviceKonto = getServiceKonto(FORM_DATA); + + assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoFactory.POSTFACH_TYPE_OSI); + } + + @Test + void shouldContainsPostfachAddresses() { + var serviceKonto = getServiceKonto(FORM_DATA); + + assertThat(serviceKonto.getPostfachAddresses()).hasSize(1); + assertThat(serviceKonto.getPostfachAddresses().get(0)).isEqualTo(POSTFACH_ADDRESS); + } + + @Test + void shouldBuildPostfachAddresses() { + getServiceKonto(FORM_DATA); + + verify(factory).buildPostfachAddresses(any(), any()); + } + } + + private ServiceKonto getServiceKonto(FormData formData) { + return factory.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData); + } + + @DisplayName("postfach addresses") + @Nested + class TestBuildPostfachAddresses { + + @DisplayName("with rest_response_name") + @Nested + class TestWithRestResponseName { + + @Test + void shouldCallBuildAddresses() { + getPostfachAddresses(); + + verify(factory).buildOsiPostfachV1Address(any(), anyInt()); + } + + @Test + void shouldReturnPostfachAddresses() { + var addresses = getPostfachAddresses(); + + assertThat(addresses).hasSize(1); + assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class); + assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId()) + .isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID); + assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoFactory.POSTFACH_VERSION); + assertThat(addresses.get(0).getType()).isEqualTo(PostfachAddressTestFactory.POSTFACH_ADDRESS_TYPE); + } + + private List<PostfachAddress> getPostfachAddresses() { + return buildServiceKonto(FORM_DATA).getPostfachAddresses(); + } + } + + @DisplayName("without rest_response_name") + @Nested + class TestWithoutRestResponseName { + + private static final FormData FORM_DATA_WITHOUT_REST_RESPONSE_NAME = FormDataUtils.from(FORM_DATA) + .remove(ServiceKontoFactory.REST_RESPONSE_NAME).build(); + + @Test + void shouldBuildDefault() { + getPostfachAddresses(); + + verify(factory).buildDefault(AfmHeaderTestFactory.POSTFACH_NAME_ID); + } + + @Test + void shouldReturnPostfachAddresses() { + var addresses = getPostfachAddresses(); + + assertThat(addresses).hasSize(1); + + assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class); + + assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId()) + .isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID); + assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoFactory.POSTFACH_VERSION); + assertThat(addresses.get(0).getType()).isEqualTo(1); + } + + private List<PostfachAddress> getPostfachAddresses() { + return buildServiceKonto(FORM_DATA_WITHOUT_REST_RESPONSE_NAME).getPostfachAddresses(); + } + } + + private ServiceKonto buildServiceKonto(FormData formData) { + return factory.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData); + } + } + } + + @Nested + class TestCreateBayernIdServicekonto { + + private final Map<String, Object> formDataHeaders = Map.of( + ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, PostfachAddressTestFactory.POSTFACH_ID, + ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, ServiceKontoTestFactory.TRUST_LEVEL + ); + + @DisplayName("should return empty when headers map is null") + @Test + void shouldReturnEmptyWhenNull() { + var serviceKonto = factory.createBayernIdServiceKonto(null); + + assertThat(serviceKonto).isEmpty(); + } + + @DisplayName("should return empty when postfach id is missing") + @Test + void shouldReturnEmptyWhenPostfachIdIsMissing() { + var serviceKonto = factory.createBayernIdServiceKonto(Map.of()); + + assertThat(serviceKonto).isEmpty(); + } + + @Test + void shouldCallIsValidTrustLevel() { + factory.createBayernIdServiceKonto(formDataHeaders); + + verify(factory).isValidTrustLevel(formDataHeaders); + } + + @Test + void shouldCallBuildBayernIdServiceKonto() { + factory.createBayernIdServiceKonto(formDataHeaders); + + verify(factory).buildBayernIdServiceKonto(formDataHeaders); + } + + @Test + void shouldReturnServiceKonto() { + var serviceKonto = ServiceKonto.builder().build(); + doReturn(serviceKonto).when(factory).buildBayernIdServiceKonto(any()); + + var result = factory.createBayernIdServiceKonto(formDataHeaders); + + assertThat(result).contains(serviceKonto); + } + + @DisplayName("should return empty when trust level has unexpected value") + @Test + void shouldReturnEmptyWhenTrustLevelCorrupted() { + doReturn(false).when(factory).isValidTrustLevel(any()); + + var serviceKonto = factory.createBayernIdServiceKonto(formDataHeaders); + + assertThat(serviceKonto).isEmpty(); + } + } + + @Nested + class TestIsValidTrustLevel { + + @Test + void shouldCallExists() { + try (var trustLevelMock = mockStatic(TrustLevel.class)) { + isValidTrustLevel(); + + trustLevelMock.verify(() -> TrustLevel.exists(ServiceKontoTestFactory.TRUST_LEVEL)); + } + } + + @Test + void shouldReturnValue() { + try (var trustLevelMock = mockStatic(TrustLevel.class)) { + trustLevelMock.when(() -> TrustLevel.exists(any())).thenReturn(true); + + var result = isValidTrustLevel(); + + assertThat(result).isTrue(); + } + } + + private boolean isValidTrustLevel() { + return factory.isValidTrustLevel(Map.of(ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, ServiceKontoTestFactory.TRUST_LEVEL)); + } + } + + @Nested + class TestBuildBayernIdServiceKonto { + + private static final String POSTFACH_ID = "postfach-id"; + private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create(); + private static final String TRUST_LEVEL = "STORK-QAA-Level-2"; + + private final Map<String, Object> formDataHeaders = Map.of( + ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, POSTFACH_ID, + ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, TRUST_LEVEL); + + @Test + void shouldSetType() { + var serviceKonto = buildBayernIdServiceKonto(); + + assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoFactory.POSTFACH_TYPE_BAYERN_ID); + } + + @Test + void shouldCallBuildPostfachAddress() { + buildBayernIdServiceKonto(); + + verify(factory).buildPostfachAddress(POSTFACH_ID); + } + + @Test + void shouldSetPostfachAddress() { + doReturn(POSTFACH_ADDRESS).when(factory).buildPostfachAddress(any()); + + var serviceKonto = buildBayernIdServiceKonto(); + + assertThat(serviceKonto.getPostfachAddresses()).containsOnly(POSTFACH_ADDRESS); + } + + @Test + void shouldCallGetTrustLevel() { + buildBayernIdServiceKonto(); + + verify(factory).getTrustLevel(formDataHeaders); + } + + @Test + void shouldSetTrustLevel() { + var serviceKonto = buildBayernIdServiceKonto(); + + assertThat(serviceKonto.getTrustLevel()).isEqualTo(TRUST_LEVEL); + } + + private ServiceKonto buildBayernIdServiceKonto() { + return factory.buildBayernIdServiceKonto(formDataHeaders); + } + } + + @Nested + class TestGetTrustLevel { + + private final Map<String, Object> formDataHeaders = Map.of(ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, + ServiceKontoTestFactory.TRUST_LEVEL); + + @Test + void shouldReturnTrustLevel() { + var trustLevel = factory.getTrustLevel(formDataHeaders); + + assertThat(trustLevel).isEqualTo(ServiceKontoTestFactory.TRUST_LEVEL); + } + + } + +} \ No newline at end of file diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java index f6e1fa7e07c716a5b00a059ea8e46c1c35d16116..3f36987c5cfe0ff4b4bb6777c7d4a595c7c43dc4 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java @@ -47,8 +47,6 @@ import org.springframework.util.MimeTypeUtils; import de.ozgcloud.common.test.TestUtils; import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.semantik.common.ReadZipException; -import de.ozgcloud.eingang.semantik.common.ZipAttachmentReader; import lombok.SneakyThrows; class ZipAttachmentReaderTest { @@ -96,7 +94,7 @@ class ZipAttachmentReaderTest { void shouldFailSilentByEncryptedZip() { var zipAttachment = createZipAttachment(ZIP_ENCRYPTED); - assertThrows(ReadZipException.class, () -> zipAttachment.readContent()); + assertThrows(ReadZipException.class, zipAttachment::readContent); } private static ZipAttachmentReader createZipAttachment(String fileName) { @@ -115,9 +113,9 @@ class ZipAttachmentReaderTest { private static Pair<String, Long> createContentPair(String fileName) { var size = switch (fileName) { - case content_file_0_name -> content_file_0_size; - case content_file_1_name -> content_file_1_size; - default -> getFileSize(fileName); + case content_file_0_name -> content_file_0_size; + case content_file_1_name -> content_file_1_size; + default -> getFileSize(fileName); }; return Pair.of(fileName, size); } @@ -189,7 +187,7 @@ class ZipAttachmentReaderTest { var zipAttachment = ZipAttachmentReader.from(invalidZip, "invalid"); - assertThrows(ReadZipException.class, () -> zipAttachment.readContent()); + assertThrows(ReadZipException.class, zipAttachment::readContent); } @Test @@ -319,4 +317,4 @@ class ZipAttachmentReaderTest { private static String getTmpDirectoryPath() { return TMP_DIRECTORY_PATH.endsWith("/") ? TMP_DIRECTORY_PATH.substring(0, TMP_DIRECTORY_PATH.length() - 1) : TMP_DIRECTORY_PATH; } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelperTest.java deleted file mode 100644 index 8d49520d80e2d2ef27042b0dc2399202e44466c9..0000000000000000000000000000000000000000 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelperTest.java +++ /dev/null @@ -1,171 +0,0 @@ -package de.ozgcloud.eingang.semantik.enginebased; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -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.Spy; - -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.FormDataUtils; -import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; -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.eingang.semantik.enginebased.afm.AfmHeaderTestFactory; - -class ServiceKontoBuildHelperTest { - - @Spy - @InjectMocks - private ServiceKontoBuildHelper helper; - - @DisplayName("OSI service konto") - @Nested - class TestOsiServiceKonto { - - private static final FormData FORM_DATA = FormData.builder().formData(AfmHeaderTestFactory.createFormDataMap()).build(); - - @DisplayName("with configured postfach") - @Nested - class TestWithConfiguredPostfach { - - private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create(); - - @BeforeEach - void mockBuildPostfachAddresses() { - doReturn(List.of(POSTFACH_ADDRESS)).when(helper).buildPostfachAddresses(any(), any()); - } - - @Test - void shouldContainsType() { - var serviceKonto = getServiceKonto(FORM_DATA); - - assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_TYPE_OSI); - } - - @Test - void shouldContainsPostfachAddresses() { - var serviceKonto = getServiceKonto(FORM_DATA); - - assertThat(serviceKonto.getPostfachAddresses()).hasSize(1); - assertThat(serviceKonto.getPostfachAddresses().get(0)).isEqualTo(POSTFACH_ADDRESS); - } - - @Test - void shouldBuildPostfachAddresses() { - getServiceKonto(FORM_DATA); - - verify(helper).buildPostfachAddresses(any(), any()); - } - } - - private ServiceKonto getServiceKonto(FormData formData) { - return helper.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData); - } - - @DisplayName("postfach addresses") - @Nested - class TestBuildPostfachAddresses { - - @DisplayName("with rest_response_name") - @Nested - class TestWithRestResponseName { - - @Test - void shouldCallBuildAddresses() { - getPostfachAddresses(); - - verify(helper).buildOsiPostfachV1Address(any(), anyInt()); - } - - @Test - void shouldReturnPostfachAddresses() { - var addresses = getPostfachAddresses(); - - assertThat(addresses).hasSize(1); - assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class); - assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId()) - .isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID); - assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_VERSION); - assertThat(addresses.get(0).getType()).isEqualTo(PostfachAddressTestFactory.POSTFACH_ADDRESS_TYPE); - } - - private List<PostfachAddress> getPostfachAddresses() { - return buildServiceKonto(FORM_DATA).getPostfachAddresses(); - } - } - - @DisplayName("without rest_response_name") - @Nested - class TestWithoutRestResponseName { - - private static final FormData FORM_DATA_WITHOUT_REST_RESPONSE_NAME = FormDataUtils.from(FORM_DATA) - .remove(ServiceKontoBuildHelper.REST_RESPONSE_NAME).build(); - - @Test - void shouldBuildDefault() { - getPostfachAddresses(); - - verify(helper).buildDefault(AfmHeaderTestFactory.POSTFACH_NAME_ID); - } - - @Test - void shouldReturnPostfachAddresses() { - var addresses = getPostfachAddresses(); - - assertThat(addresses).hasSize(1); - - assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class); - - assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId()) - .isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID); - assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_VERSION); - assertThat(addresses.get(0).getType()).isEqualTo(1); - } - - private List<PostfachAddress> getPostfachAddresses() { - return buildServiceKonto(FORM_DATA_WITHOUT_REST_RESPONSE_NAME).getPostfachAddresses(); - } - } - - private ServiceKonto buildServiceKonto(FormData formData) { - return helper.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData); - } - } - } - - @Nested - class TestBayernIdServiceKonto { - - private static final String POSTFACH_ID = "postfach-id"; - private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create(); - - @Test - void shouldSetType() { - var serviceKonto = buildBayernIdServiceKonto(); - - assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_TYPE_BAYERN_ID); - } - - @Test - void shouldSetPostfachAddress() { - doReturn(POSTFACH_ADDRESS).when(helper).buildPostfachAddress(any()); - - var serviceKonto = buildBayernIdServiceKonto(); - - assertThat(serviceKonto.getPostfachAddresses()).containsOnly(POSTFACH_ADDRESS); - } - - ServiceKonto buildBayernIdServiceKonto() { - return helper.buildBayernIdServiceKonto(POSTFACH_ID); - } - } -} \ No newline at end of file diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12FormDataMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12FormDataMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aa4ee4fda33b39b15dfac04de58939b1dfcc18d1 --- /dev/null +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/a12/A12FormDataMapperTest.java @@ -0,0 +1,93 @@ +package de.ozgcloud.eingang.semantik.enginebased.a12; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.Optional; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Spy; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import de.ozgcloud.common.binaryfile.TempFileUtils; +import de.ozgcloud.common.test.TestUtils; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormData.FormDataControl; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; + +class A12FormDataMapperTest { + + @Spy + @InjectMocks + private A12FormDataMapper mapper; + + @Spy + private ObjectMapper objectMapper = new ObjectMapper(); + + @Nested + class TestParseFormData { + + @Test + void shouldGetFormDataFile() { + var formData = buildInputFormData(); + + mapper.parseFormData(formData); + + verify(mapper).getFormDataFile(same(formData)); + } + } + + @Nested + class TestGetFormDataFile { + @Test + void shouldReturnFile() { + var inFile = mapper.getFormDataFile(buildInputFormData()); + + assertThat(inFile).get().usingRecursiveComparison().ignoringFields("file").isEqualTo(buildFormDataInFile()); + } + + @Test + void shouldCheckIfFound() { + mapper.getFormDataFile(FormDataTestFactory.create()); + + verify(mapper).logWarnIfEmpty(Optional.empty()); + } + } + + private FormData buildInputFormData() { + return FormDataTestFactory.createBuilder() + .control(FormDataControl.builder() + .representations(Optional.of(Representations.builder().primaryFormDataRepresentation("A12FormData.json").build())).build()) + .representation(buildFormDataInFile()) + .build(); + } + + private IncomingFile buildFormDataInFile() { + return IncomingFileTestFactory.createBuilder() + .contentType("application/json") + .name("A12FormData.json") + .file(TempFileUtils.writeTmpFile(TestUtils.loadFile("A12/a12FormData.json"))) + .build(); + } + + @Nested + class TestReadEingang { + + @Test + void shouldReadJson() { + var file = TempFileUtils.writeTmpFile(TestUtils.loadFile("A12/a12FormData.json")); + + var result = mapper.readEingang(file); + + assertThat(result).isNotNull(); + } + } + +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java index 953ff17d4427885712c3d95f1b9524b0b1dc1bc1..c5c99d30268b7e40f00ef05af208d0a346052bd0 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java @@ -20,6 +20,7 @@ import org.mockito.Spy; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; class AfmAntragstellerHeaderMapperTest { @@ -145,7 +146,7 @@ class AfmAntragstellerHeaderMapperTest { @Test void shouldApproveResponsibility() { doReturn(true).when(mapper).isPostfachIdNotBlank(any()); - doReturn(createHeaders(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, "123")).when(mapper).getHeaders(any()); + doReturn(createHeaders(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, "123")).when(mapper).getHeaders(any()); var isResponsible = mapper.isResponsible(formData); @@ -173,8 +174,9 @@ class AfmAntragstellerHeaderMapperTest { assertFalse(isResponsible); } + @Test void shouldDenyWhenPostfachIdIsBlank() { - doReturn(createHeaders(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, null)).when(mapper).getHeaders(any()); + doReturn(createHeaders(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, null)).when(mapper).getHeaders(any()); doReturn(false).when(mapper).isPostfachIdNotBlank(any()); var isResponsible = mapper.isResponsible(formData); @@ -215,7 +217,7 @@ class AfmAntragstellerHeaderMapperTest { @Test void shouldReturnHeaders() { - var headers = createHeaders(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, "123"); + var headers = createHeaders(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, "123"); var formData = FormData.builder().formData(createHeaders(AfmHeaderMapper.HEADER_FIELD, headers)).build(); var result = mapper.getHeaders(formData); 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 ff4575a298712beaa7bdc0e8cbe035e83b9c714e..609284d26fccdb41ed91818c5df7ed0161990cdc 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 @@ -24,11 +24,9 @@ package de.ozgcloud.eingang.semantik.enginebased.afm; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.Collections; -import java.util.List; import java.util.Map; import org.junit.jupiter.api.BeforeEach; @@ -41,50 +39,58 @@ import org.mockito.Spy; import org.springframework.test.util.ReflectionTestUtils; import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmAntragstellerMapper; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedAdapter; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedMapper; +import de.ozgcloud.eingang.common.formdata.FormHeader; +import de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.IntelliFormRepresentationAdapter; class AfmEngineBasedAdapterTest { @Spy @InjectMocks private AfmEngineBasedAdapter adapter; - @Spy - private List<EngineBasedMapper> mappers; @Mock private AfmEngineBasedMapper mapper; + @Mock + private IntelliFormRepresentationAdapter intelliFormRepresentationAdapters; + @DisplayName("Parse form data") @Nested class TestParseFromData { + private final String VORGANG_NUMMER = "AAAA-1234"; private final Map<String, Object> formDataMap = Map.of(AfmAntragstellerMapper.POSTFACH_ID, "postfachIdValue"); - private final FormData formData = FormData.builder().formData(formDataMap).build(); + private final FormData formData = FormData.builder() + .header(FormHeader.builder() + .vorgangNummer(VORGANG_NUMMER) + .build() + ) + .formData(formDataMap) + .build(); + + private final FormData processedFormData = FormData.builder() + .formData(formDataMap) + .build(); @BeforeEach - void mockMappers() { + void mock() { ReflectionTestUtils.setField(adapter, "mappers", Collections.singletonList(mapper)); - } - @BeforeEach - void mockEngineBasedMapper() { - when(mapper.parseFormData(any())).thenReturn(formData); + when(mapper.parseFormData(processedFormData)).thenReturn(processedFormData); + when(intelliFormRepresentationAdapters.adaptByRepresentations(formData)).thenReturn(processedFormData); } @Test - void shouldCallMappers() { + void shouldCallRepresentationAdapter() { adapter.parseFormData(formData); - verify(mapper).parseFormData(formData); + verify(intelliFormRepresentationAdapters).adaptByRepresentations(formData); } @Test - void shouldRemoveProcessedData() { + void shouldCallMappers() { adapter.parseFormData(formData); - verify(adapter).removeProcessedData(formData); + verify(mapper).parseFormData(processedFormData); } @Test @@ -93,5 +99,14 @@ 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/AfmAttachedFilesMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapperTest.java similarity index 75% rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapperTest.java rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapperTest.java index 2643740ae163291151e0573b6b9537514ce0b831..7c63ef8ed048579653880f4ef7904f0b97d9554a 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapperTest.java @@ -26,44 +26,40 @@ package de.ozgcloud.eingang.semantik.enginebased.afm; import static org.assertj.core.api.Assertions.*; import java.util.List; -import java.util.Map; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; -import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmAttachedFilesMapper; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Spy; -class AfmAttachedFilesMapperTest { +class AfmFileCountMapperTest { @Spy @InjectMocks - private AfmAttachedFilesMapper mapper; + private AfmFileCountMapper mapper; - private IncomingFileGroup attachmentWithMultipleFiles = IncomingFileGroupTestFactory.createBuilder() + private final IncomingFileGroup attachmentWithMultipleFiles = IncomingFileGroupTestFactory.createBuilder() .name("anotherAttachment") .clearFiles() .files(List.of(IncomingFileTestFactory.create(), IncomingFileTestFactory.create())) .build(); - private FormData formData = FormDataTestFactory.createBuilder() + private final FormData formData = FormDataTestFactory.createBuilder() .clearAttachments() - .formData(Map.of(FilesMapperHelper.FIELD_NAME_MAPPED_FILES, - Map.of(FilesMapperHelper.ATTACHMENTS, List.of(IncomingFileGroupTestFactory.create(), attachmentWithMultipleFiles)))) + .attachments(List.of(IncomingFileGroupTestFactory.create(), attachmentWithMultipleFiles)) .build(); @Nested class TestParseFormData { @Test - void shouldMapAttachments() { + void shouldKeepAttachments() { var parsedFormData = parseFormData(); assertThat(parsedFormData.getAttachments()).hasSize(2); @@ -79,7 +75,7 @@ class AfmAttachedFilesMapperTest { } @Test - void shouldMapRepresentations() { + void shouldKeepRepresentations() { var parsedFormData = parseFormData(); assertThat(parsedFormData.getRepresentations()).hasSize(1); @@ -92,15 +88,8 @@ class AfmAttachedFilesMapperTest { assertThat(parsedFormData.getNumberOfRepresentations()).isEqualTo(1); } - @Test - void shouldRemoveFilesFromMap() { - var parsedFormData = parseFormData(); - - assertThat(parsedFormData.getFormData().get(FilesMapperHelper.FIELD_NAME_MAPPED_FILES)).isNull(); - } - private FormData parseFormData() { return mapper.parseFormData(formData); } } -} \ No newline at end of file +} 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 93ddc2f4f3e24d4dd2b4c045e6a4d8e39a23086c..7af0dcd5c208e6c3989c0e8be54948e382c45ac6 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 @@ -27,7 +27,6 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.DisplayName; @@ -40,7 +39,7 @@ import org.mockito.Spy; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataUtils; import de.ozgcloud.eingang.common.formdata.ServiceKonto; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; class AfmHeaderMapperTest { @@ -48,7 +47,7 @@ class AfmHeaderMapperTest { @InjectMocks private AfmHeaderMapper mapper; @Mock - private ServiceKontoBuildHelper serviceKontoBuildHelper; + private ServiceKontoFactory serviceKontoFactory; @DisplayName("Parse form data") @Nested @@ -124,14 +123,14 @@ class AfmHeaderMapperTest { void shouldCallBuildServiceKontoIfPresent() { parseFormData(); - verify(serviceKontoBuildHelper).buildOsiServiceKonto(any(), eq(FORM_DATA)); + verify(serviceKontoFactory).buildOsiServiceKonto(any(), eq(FORM_DATA)); } @Test void shouldNotCallBuildServiceKontoIfNotExists() { mapper.parseFormData(FormDataUtils.from(FORM_DATA).remove(AfmHeaderMapper.POSTFACH_NAME_ID).build()); - verify(serviceKontoBuildHelper, never()).buildOsiServiceKonto(any(), any()); + verify(serviceKontoFactory, never()).buildOsiServiceKonto(any(), any()); } } @@ -155,22 +154,13 @@ class AfmHeaderMapperTest { @Test void shouldReturnServiceKonto() { - doReturn(Optional.of("id")).when(mapper).getPostfachId(any()); - when(serviceKontoBuildHelper.buildBayernIdServiceKonto(any())).thenReturn(serviceKonto); + when(serviceKontoFactory.createBayernIdServiceKonto(any())).thenReturn(Optional.of(serviceKonto)); var parsedFormData = mapper.createBayernIdServiceKonto(formData); - assertThat(parsedFormData).isPresent().get().isEqualTo(serviceKonto); + assertThat(parsedFormData).contains(serviceKonto); } - @Test - void shouldNotCallServiceKontoBuildHelper() { - doReturn(Optional.empty()).when(mapper).getPostfachId(any()); - - mapper.createBayernIdServiceKonto(formData); - - verify(serviceKontoBuildHelper, never()).buildBayernIdServiceKonto(any()); - } } } } @@ -190,7 +180,7 @@ class AfmHeaderMapperTest { void shouldRemoveRestResponseName() { var parsedFormData = parseFormData(); - assertThat(parsedFormData.getFormData().get(ServiceKontoBuildHelper.REST_RESPONSE_NAME)).isNull(); + assertThat(parsedFormData.getFormData().get(ServiceKontoFactory.REST_RESPONSE_NAME)).isNull(); } private FormData parseFormData() { @@ -199,28 +189,4 @@ class AfmHeaderMapperTest { } } - @Nested - class TestGetPostfachId { - - @Mock - private FormData formData; - - @Test - void shouldReturnPostfachId() { - doReturn(Map.of(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, AfmAntragstellerTestFactory.POSTFACH_ID)).when(mapper).getHeaderMap(any()); - - var postfachId = mapper.getPostfachId(formData); - - assertThat(postfachId).isPresent().get().isEqualTo(AfmAntragstellerTestFactory.POSTFACH_ID); - } - - @Test - void shouldReturnEmpty() { - doReturn(null).when(mapper).getHeaderMap(any()); - - var postfachId = mapper.getPostfachId(formData); - - assertThat(postfachId).isEmpty(); - } - } } \ No newline at end of file diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java index 4cdd6b5f7ed887dbd9841e0d844b5389b25bb366..ff8b85d511d22fd84c3a3302d29c2fe58b31eb78 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java @@ -28,7 +28,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; public class AfmHeaderTestFactory { @@ -57,7 +57,7 @@ public class AfmHeaderTestFactory { var map = new HashMap<String, Object>(); map.put(AfmHeaderMapper.HEADER_FIELD, createHeaderMap()); map.put(AfmHeaderMapper.POSTFACH_NAME_ID, POSTFACH_NAME_ID); - map.put(ServiceKontoBuildHelper.REST_RESPONSE_NAME, List.of(createRestResponseNameMap())); + map.put(ServiceKontoFactory.REST_RESPONSE_NAME, List.of(createRestResponseNameMap())); return map; } @@ -81,7 +81,7 @@ public class AfmHeaderTestFactory { public static Map<String, Object> createCustomHeaderMap() { var map = new HashMap<String, Object>(); - map.put(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, CUSTOM_POSTFACH_ID); + map.put(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, CUSTOM_POSTFACH_ID); map.put(AfmAntragstellerHeaderMapper.KEY_VORNAME, CUSTOM_VORNAME); map.put(AfmAntragstellerHeaderMapper.KEY_NACHNAME, CUSTOM_NACHNAME); map.put(AfmAntragstellerHeaderMapper.KEY_GEBURTSNAME, CUSTOM_GEBURTSNAME); @@ -95,10 +95,10 @@ public class AfmHeaderTestFactory { } public static Map<String, Object> createRestResponseNameMap() { - return Map.of(ServiceKontoBuildHelper.REST_RESPONSE_NAME_MEMBER_SCOPE, List.of(createRestResponseNameMemberScopeMap())); + return Map.of(ServiceKontoFactory.REST_RESPONSE_NAME_MEMBER_SCOPE, List.of(createRestResponseNameMemberScopeMap())); } private static Map<String, Object> createRestResponseNameMemberScopeMap() { - return Map.of(ServiceKontoBuildHelper.REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE, REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE_VALUE); + return Map.of(ServiceKontoFactory.REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE, REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE_VALUE); } } \ No newline at end of file diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..27be6b86a22cc6658bb7421265e3b914fb990817 --- /dev/null +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapterTest.java @@ -0,0 +1,456 @@ +package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform; + +import static de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.IntelliFormRepresentationAdapter.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +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.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import com.thedeanda.lorem.LoremIpsum; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; + +class IntelliFormRepresentationAdapterTest { + + private static final String DOCUMENT_TEST_KEY = "doc-test-key"; + private static final String DOCUMENT_TEST_VALUE = "doc-test-value"; + + @Spy + @InjectMocks + IntelliFormRepresentationAdapter adapter; + + @Mock + private XmlToJavaMapsMapper xmlToJavaMapsMapper; + + @DisplayName("find IntelliForm XML representation") + @Nested + class TestFindIntelliFormXmlRepresentation { + + @Mock + private FormData formData; + + @DisplayName("should find first with IntelliForm schema") + @Test + void shouldFindFirstWithIntelliFormSchema() { + var schemas = Stream.of( + "<root xmlns=\"%s\" />".formatted(INTELLIFORM_TYPENAME), + "<root xmlns:t=\"unknown\">first</root>", + "<root>second</root>", + "<root xmlns:t=\"%s\">third</root>".formatted(INTELLIFORM_TYPENAME), + "<root xmlns:t=\"%s\">fourth</root>".formatted(INTELLIFORM_TYPENAME) + ).map(IntelliFormRepresentationAdapterTest.this::buildXMLDocument); + doReturn(schemas).when(adapter).streamXMLDocumentsFromRepresentations(formData); + + var firstWithSchema = adapter.findIntelliFormXMLRepresentation(formData); + + assertThat(firstWithSchema).isPresent(); + var rootElement = firstWithSchema.get().getDocumentElement(); + assertThat(rootElement.getTextContent()).isEqualTo("third"); + } + } + + @DisplayName("stream XML documents from representations") + @Nested + class TestStreamXmlDocumentsFromRepresentations { + + @Mock + private Document document; + + @Mock + private FormData formData; + + @Mock + private InputStream inputStream; + + @DisplayName("with no representations") + @Nested + class TestWithNoRepresentations { + @BeforeEach + void mock() { + when(formData.getRepresentations()).thenReturn(Collections.emptyList()); + } + + @DisplayName("should return empty") + @Test + void shouldReturnEmpty() { + var documents = doExtract(); + + assertThat(documents).isEmpty(); + } + } + + @DisplayName("with a xml representation") + @Nested + class TestWithAXMLRepresentations { + @Mock + private IncomingFile otherRepresentation; + + @Mock + private IncomingFile xmlRepresentation; + + @Mock + private IncomingFile otherXMLRepresentation; + + @Mock + private Document otherDocument; + + @Mock + private InputStream otherInputStream; + + @BeforeEach + void mock() { + when(otherRepresentation.getContentType()).thenReturn("pdf"); + when(xmlRepresentation.getContentType()).thenReturn("xml"); + when(otherXMLRepresentation.getContentType()).thenReturn("xml"); + when(formData.getRepresentations()).thenReturn(List.of(otherRepresentation, xmlRepresentation, otherXMLRepresentation)); + + when(xmlRepresentation.getContentStream()).thenReturn(inputStream); + when(xmlToJavaMapsMapper.parseAsW3cDocument(inputStream)).thenReturn(document); + + when(otherXMLRepresentation.getContentStream()).thenReturn(otherInputStream); + + } + + @DisplayName("should include all successfully parsed documents") + @Test + void shouldIncludeAllSuccessfullyParsedDocuments() { + when(xmlToJavaMapsMapper.parseAsW3cDocument(otherInputStream)).thenReturn(otherDocument); + + var documents = doExtract(); + + assertThat(documents).isEqualTo(List.of(document, otherDocument)); + } + + @DisplayName("should skip documents with parse error") + @Test + void shouldSkipDocumentsWithParseError() { + when(xmlToJavaMapsMapper.parseAsW3cDocument(otherInputStream)).thenThrow(new TechnicalException("some error")); + + var documents = doExtract(); + + assertThat(documents).isEqualTo(List.of(document)); + } + } + + private List<Document> doExtract() { + return adapter.streamXMLDocumentsFromRepresentations(formData).toList(); + } + } + + @DisplayName("is responsible") + @Nested + class TestIsResponsible { + + @Mock + private FormData formData; + + @DisplayName("should be true with namespace attribute match") + @Test + void shouldBeTrueWithNamespaceAttributeMatch() { + + doReturn(Optional.of(buildXMLDocument(""" + <myForm xmlns:t="%s"> + </myForm>""".formatted(INTELLIFORM_TYPENAME)))) + .when(adapter).findIntelliFormXMLRepresentation(formData); + + var isResponsible = adapter.isResponsible(formData); + + assertThat(isResponsible).isTrue(); + } + + @DisplayName("should be false without xml document") + @Test + void shouldBeFalseWithoutXmlDocument() { + doReturn(Optional.empty()) + .when(adapter).findIntelliFormXMLRepresentation(formData); + + var isResponsible = adapter.isResponsible(formData); + + assertThat(isResponsible).isFalse(); + } + + } + + @DisplayName("get form data entries from document") + @Nested + class TestGetFormDataEntriesFromDocument { + + private static final String OTHER_VENDOR_ID = "vendorId:other"; + private static final String MISSING_VENDOR_ID = "vendorId:missing"; + + @Mock + private Document document; + + private List<IncomingFileGroup> attachments; + + @BeforeEach + void mock() { + when(xmlToJavaMapsMapper.mapXmlToJavaMaps(document)).thenReturn(Map.of( + DOCUMENT_TEST_KEY, DOCUMENT_TEST_VALUE, + "Upload1", Map.of( + "file", Map.of("id", IncomingFileGroupTestFactory.VENDOR_ID_XXX) + ), + "Upload2", Map.of( + "file", Map.of("id", OTHER_VENDOR_ID) + ), + "Upload3", Map.of( + "file", Map.of("id", "representationId") + ), + "NoUpload1", Map.of( + "file", "" + ), + "NoUpload2", Map.of() + )); + attachments = List.of( + IncomingFileGroupTestFactory.create(), + IncomingFileGroupTestFactory.createBuilder() + .name("other") + .files(List.of( + IncomingFileTestFactory.createBuilder() + .vendorId(MISSING_VENDOR_ID) + .build(), + IncomingFileTestFactory.createBuilder() + .vendorId(OTHER_VENDOR_ID) + .build())) + .build()); + + } + + @DisplayName("should prune upload element if is an attachment") + @Test + void shouldPruneUploadElementIfIsAnAttachment() { + var entryKeys = obtainResidualEntryKeys(); + + assertThat(entryKeys).containsExactlyInAnyOrder(DOCUMENT_TEST_KEY, "Upload3", "NoUpload1", "NoUpload2"); + } + + private List<String> obtainResidualEntryKeys() { + return adapter.getFormDataEntriesFromDocument(document, attachments).map(Map.Entry::getKey).toList(); + } + } + + @DisplayName("create header map") + @Nested + class TestCreateHeaderMap { + + private Document document; + + @DisplayName("with full fields") + @Nested + class TestWithFullFields { + + private Map<String, Object> headerMap; + + @BeforeEach + void mock() { + headerMap = Stream.concat(HEADER_ATTRIBUTE_NAMES.stream(), CUSTOM_HEADER_ATTRIBUTE_NAMES.stream()) + .collect(Collectors.toMap(name -> name, name -> LoremIpsum.getInstance().getName())); + document = buildXMLDocument("<root %s/>".formatted( + headerMap.entrySet().stream() + .map(entry -> "%s=\"%s\"".formatted(entry.getKey(), entry.getValue())) + .collect(Collectors.joining(" ")) + ) + ); + } + + @DisplayName("should include header field") + @ParameterizedTest + @MethodSource("headerNames") + void shouldIncludeAllHeaderField(String headerName) { + var resultHeaderMap = adapter.createHeaderMap(document); + + assertThat(resultHeaderMap).containsEntry(headerName, headerMap.get(headerName)); + } + + private static Stream<Arguments> headerNames() { + return HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of); + } + + @DisplayName("should include custom header field") + @ParameterizedTest + @MethodSource("customHeaderNames") + void shouldIncludeAllCustomHeaderField(String headerName) { + var resultHeaderMap = adapter.createHeaderMap(document); + + assertThat(resultHeaderMap).containsEntry(headerName, headerMap.get(headerName)); + } + + private static Stream<Arguments> customHeaderNames() { + return CUSTOM_HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of); + } + } + + @DisplayName("with empty fields") + @Nested + class TestWithEmptyFields { + @BeforeEach + void mock() { + document = buildXMLDocument("<root />"); + } + + @DisplayName("should include empty header field") + @ParameterizedTest + @MethodSource("headerNames") + void shouldIncludeAllHeaderField(String headerName) { + var resultHeaderMap = adapter.createHeaderMap(document); + + assertThat(resultHeaderMap).containsEntry(headerName, ""); + } + + private static Stream<Arguments> headerNames() { + return HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of); + } + + @DisplayName("should not include custom header field") + @ParameterizedTest + @MethodSource("customHeaderNames") + void shouldNotIncludeAllCustomHeaderField(String headerName) { + var resultHeaderMap = adapter.createHeaderMap(document); + + assertThat(resultHeaderMap).doesNotContainKey(headerName); + } + + private static Stream<Arguments> customHeaderNames() { + return CUSTOM_HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of); + } + } + } + + @DisplayName("adapt by representation") + @Nested + class TestAdaptByRepresentation { + + @Mock + private FormData formData; + + @DisplayName("should throw exception without xml document") + @Test + void shouldThrowExceptionWithoutXmlDocument() { + doReturn(Optional.empty()) + .when(adapter).findIntelliFormXMLRepresentation(formData); + + assertThrows(TechnicalException.class, () -> + adapter.adaptByRepresentations(formData) + ); + } + + @DisplayName("with xml document") + @Nested + class TestWithXmlDocument { + + @Mock + private IncomingFileGroup attachmentGroup; + + @Mock + private IncomingFile xmlRepresentation; + + @Mock + private IncomingFile otherRepresentation; + + @Mock + private Document document; + + @Mock + private Map<String, Object> headerFields; + + private List<IncomingFileGroup> attachments; + private List<IncomingFile> representations; + + @BeforeEach + void mock() { + attachments = List.of(attachmentGroup); + representations = List.of(xmlRepresentation, otherRepresentation); + + when(formData.getRepresentations()).thenReturn(representations); + when(formData.getAttachments()).thenReturn(attachments); + doReturn(Optional.of(document)).when(adapter).findIntelliFormXMLRepresentation(formData); + + doReturn(Map.of(DOCUMENT_TEST_KEY, DOCUMENT_TEST_VALUE).entrySet().stream()) + .when(adapter).getFormDataEntriesFromDocument(document, attachments); + + doReturn(headerFields) + .when(adapter).createHeaderMap(document); + } + + @DisplayName("should have document field") + @Test + void shouldHaveDocumentField() { + var documentValue = obtainMappingByKey(DOCUMENT_TEST_KEY); + + assertThat(documentValue).isEqualTo(DOCUMENT_TEST_VALUE); + } + + @DisplayName("should have header field") + @Test + void shouldHaveHeaderField() { + var headerValue = obtainMappingByKey(HEADER_FIELD); + + assertThat(headerValue).isEqualTo(headerFields); + } + + private Object obtainMappingByKey(String key) { + var formDataResult = adapter.adaptByRepresentations(formData); + + return formDataResult.getFormData().get(key); + } + + @DisplayName("should have attachments") + @Test + void shouldHaveAttachments() { + var formDataResult = adapter.adaptByRepresentations(formData); + + assertThat(formDataResult.getAttachments()).isEqualTo(attachments); + } + + @DisplayName("should have representations") + @Test + void shouldHaveRepresentations() { + var formDataResult = adapter.adaptByRepresentations(formData); + + assertThat(formDataResult.getRepresentations()).isEqualTo(representations); + } + } + } + + private Document buildXMLDocument(String xmlString) { + try { + return DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(new InputSource(new StringReader(xmlString))); + } catch (ParserConfigurationException | IOException | SAXException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/JsonServiceTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonServiceTest.java similarity index 94% rename from intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/JsonServiceTest.java rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonServiceTest.java index e32bfa9c633fa6e36169d7b0674f59ab0c4ca59f..c9212b4dc604a48ae5a085da63b7ac3d62720087 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/JsonServiceTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonServiceTest.java @@ -1,4 +1,4 @@ -package de.ozgcloud.eingang.intelliform; +package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.JsonService; import lombok.SneakyThrows; class JsonServiceTest { diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapperTest.java similarity index 99% rename from intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapperTest.java rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapperTest.java index ea6f5149f2aaba2246891aaefede93950f120a7d..37df5097b555ee8308b53570108c02024fc2745f 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapperTest.java @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.eingang.intelliform; +package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -31,8 +31,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import jakarta.xml.soap.Node; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -40,6 +38,7 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.w3c.dom.Document; +import org.w3c.dom.Node; import de.ozgcloud.common.errorhandling.TechnicalException; @@ -327,4 +326,4 @@ class XmlToJavaMapsMapperTest { private Map<String, Object> mapXmlToJavaMaps() { return mapper.mapXmlToJavaMaps(document); } -} \ No newline at end of file +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapterTest.java similarity index 53% rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapperTest.java rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapterTest.java index dc9d2d172dde4c1e84debbc0bb270e3e3437e8cb..05473793842bc54d734988d7cf1ad872d5789b7a 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapterTest.java @@ -1,4 +1,4 @@ -package de.ozgcloud.eingang.semantik.formbased; +package de.ozgcloud.eingang.semantik.enginebased.dfoerdermittel; import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.InstanceOfAssertFactories.*; @@ -11,8 +11,6 @@ import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; @@ -26,30 +24,30 @@ import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory; import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory; import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; -class DFoerdermittelFormBasedMapperTest { +class DFoerdermittelEngineBasedSemantikAdapterTest { @Spy @InjectMocks - private DFoerdermittelFormBasedMapper mapper; + private DFoerdermittelEngineBasedSemantikAdapter adapter; @Mock - private ServiceKontoBuildHelper serviceKontoHelper; + private ServiceKontoFactory serviceKontoFactory; @Nested class TestIsResponsible { @Test void shouldBeTrueWithFachnachricht() { - var responsible = mapper.isResponsible(createWithFachnachricht()); + var responsible = adapter.isResponsible(createWithFachnachricht()); assertThat(responsible).isTrue(); } @Test void shouldBeFalseForOuther() { - var responsible = mapper.isResponsible(FormDataTestFactory.create()); + var responsible = adapter.isResponsible(FormDataTestFactory.create()); assertThat(responsible).isFalse(); } @@ -62,21 +60,21 @@ class DFoerdermittelFormBasedMapperTest { class ExtractData { @Test void shouldHaveFormData() { - var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); + var result = adapter.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); assertThat(result).isNotNull(); } @Test void shouldHavePages() { - var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); + var result = adapter.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); assertThat(result).containsKey("Pages"); } @Test void shouldHaveInboxRef() { - var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); + var result = adapter.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); assertThat(result).containsEntry("InboxReference", "sh/sh/4dd01647-b9d9-4775-1b50-08da3d83800a"); } @@ -89,27 +87,27 @@ class DFoerdermittelFormBasedMapperTest { @Test void shouldCallExtractData() { - doReturn(extracted).when(mapper).extractFormDataFormXML(any()); + doReturn(extracted).when(adapter).extractFormDataFormXML(any()); - mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); + adapter.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); - verify(mapper).extractFormDataFormXML(notNull()); + verify(adapter).extractFormDataFormXML(notNull()); } @Test void shouldAddMap() { - doReturn(extracted).when(mapper).extractFormDataFormXML(any()); + doReturn(extracted).when(adapter).extractFormDataFormXML(any()); - var result = mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); + var result = adapter.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); assertThat(result.getFormData()).containsEntry("Fachnachricht", extracted); } @Test void shouldIgnoreEmptyData() { - doReturn(Collections.emptyMap()).when(mapper).extractFormDataFormXML(any()); + doReturn(Collections.emptyMap()).when(adapter).extractFormDataFormXML(any()); - var result = mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); + var result = adapter.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); assertThat(result.getFormData()).doesNotContainKey("Fachnachricht"); } @@ -137,27 +135,37 @@ class DFoerdermittelFormBasedMapperTest { @Nested class TestProcessFachnachricht { - @Captor - private ArgumentCaptor<Map<String, Object>> fachnachrichtCaptor; + @Mock + FormData formData0; - @Test - void shouldCallAddServiceKonto() { - var formData = DFoerdermittelFormDataTestFactory.create(); + @Mock + FormData formData1; + + @Mock + FormData formData2; - mapper.processFachnachricht(formData); + @Mock + FormData formData3; - verify(mapper).addServiceKonto(same(formData), fachnachrichtCaptor.capture()); - assertThat(fachnachrichtCaptor.getValue()).containsAllEntriesOf(DFoerdermittelFormDataTestFactory.createFachnachrichtMap()); + @Mock + FormData formData4; + + @BeforeEach + void mock() { + var formData = DFoerdermittelFormDataTestFactory.create(); + var fachnachrichtMap = DFoerdermittelFormDataTestFactory.createFachnachrichtMap(); + when(formData0.getFormData()).thenReturn(formData.getFormData()); + doReturn(formData1).when(adapter).addFormName(formData0); + doReturn(formData2).when(adapter).addFormEngineName(formData1); + doReturn(formData3).when(adapter).addServiceKonto(formData2, fachnachrichtMap); + doReturn(formData4).when(adapter).addOrganisationsEinheitId(formData3, fachnachrichtMap); } @Test - void shouldCallAddOrganisationsEinheitId() { - var extened = DFoerdermittelFormDataTestFactory.create(); - doReturn(extened).when(mapper).addServiceKonto(any(), any()); + void shouldReturn() { + var processedFormData = adapter.processFachnachricht(formData0); - mapper.processFachnachricht(DFoerdermittelFormDataTestFactory.create()); - - verify(mapper).addOrganisationsEinheitId(same(extened), notNull()); + assertThat(processedFormData).isEqualTo(formData4); } } @@ -166,12 +174,12 @@ class DFoerdermittelFormBasedMapperTest { @BeforeEach void init() { - when(serviceKontoHelper.buildOsiServiceKonto(any())).thenReturn(ServiceKontoTestFactory.create()); + when(serviceKontoFactory.buildOsiServiceKonto(any())).thenReturn(ServiceKontoTestFactory.create()); } @Test void shouldHaveServiceKonto() { - var formData = mapper.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), + var formData = adapter.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap()); assertThat(formData.getHeader().getServiceKonto().getPostfachAddresses().get(0).getIdentifier()) @@ -181,9 +189,9 @@ class DFoerdermittelFormBasedMapperTest { @Test void shouldRemovePrefix() { - mapper.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap()); + adapter.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap()); - verify(serviceKontoHelper).buildOsiServiceKonto(DFoerdermittelFormDataTestFactory.POSTFACH_ID); + verify(serviceKontoFactory).buildOsiServiceKonto(DFoerdermittelFormDataTestFactory.POSTFACH_ID); } } @@ -191,14 +199,14 @@ class DFoerdermittelFormBasedMapperTest { class TestExtractPrefix { @Test void shouldRemoveAllBeforeLastSlash() { - var result = mapper.extractPrefix("bla/bla/bla/12345"); + var result = adapter.extractPrefix("bla/bla/bla/12345"); assertThat(result).isEqualTo("12345"); } @Test void shouldBeFineWithoutSlash() { - var result = mapper.extractPrefix("12345"); + var result = adapter.extractPrefix("12345"); assertThat(result).isEqualTo("12345"); } @@ -208,11 +216,35 @@ class DFoerdermittelFormBasedMapperTest { class TestAddOrganisationsEinheitId { @Test void shouldHaveOrganisationsEinheitId() { - var formData = mapper.addOrganisationsEinheitId(DFoerdermittelFormDataTestFactory.create(), + var formData = adapter.addOrganisationsEinheitId(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap()); assertThat(formData.getZustaendigeStelle()).isNotNull().extracting(ZustaendigeStelle::getOrganisationseinheitenId) .isEqualTo(DFoerdermittelFormDataTestFactory.ORGANISATIONS_EINHEIT_ID); } } + + @Nested + class TestAddFormName { + + @Test + void shouldHaveFormName() { + var formData = adapter.addFormName(DFoerdermittelFormDataTestFactory.create()); + + assertThat(formData.getHeader().getFormName()).isEqualTo("dFördermittelantrag"); + } + + } + + @Nested + class TestAddFormEngineName { + + @Test + void shouldHaveFormEngineName() { + var formData = adapter.addFormEngineName(DFoerdermittelFormDataTestFactory.create()); + + assertThat(formData.getHeader().getFormEngineName()).isEqualTo("dFördermittelantrag"); + } + + } } diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormDataTestFactory.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelFormDataTestFactory.java similarity index 90% rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormDataTestFactory.java rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelFormDataTestFactory.java index fd333fc59cea56b4bfba0b21994f5169f305a5a4..b99c66e48559d39b5c58e747c145a58dc0490363 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormDataTestFactory.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelFormDataTestFactory.java @@ -1,4 +1,4 @@ -package de.ozgcloud.eingang.semantik.formbased; +package de.ozgcloud.eingang.semantik.enginebased.dfoerdermittel; import java.util.Map; diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java index cc186d6b99d8f020ff07374682eb34f7b751b407..47c563508627226dac6341fe8d6e4b36f9062b70 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java @@ -58,9 +58,7 @@ import lombok.SneakyThrows; public class FormSolutionsEngineBasedAdapterITCase { private static final String ZIP_CONTENT_TYPE = "application/zip"; - private static final String FILE_NAME_ZIP_ATTACHMENT = "attachment-2files.zip"; - public static final String FILE_NAME_PDF_REP = "eingang.pdf"; - public static final String FILE_NAME_JSON_REP = "form-data.json"; + private static final String FILE_NAME_ZIP_ATTACHMENT = "formsolutions/attachment-2files.zip"; @MockBean private SemantikAdapter semantikAdapter; diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java index 89c782671e7e568ffebc70299df1fc8431499a71..56df1f639ff2bac7f59b24ba6d36bf387227ee59 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java @@ -38,7 +38,7 @@ import org.mockito.Spy; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataUtils; import de.ozgcloud.eingang.common.formdata.FormHeader; -import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper; +import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory; class FormSolutionsHeaderMapperTest { @@ -46,7 +46,7 @@ class FormSolutionsHeaderMapperTest { @InjectMocks private final FormSolutionsHeaderMapper mapper = new FormSolutionsHeaderMapper(); @Mock - private ServiceKontoBuildHelper serviceKontoBuildHelper; + private ServiceKontoFactory serviceKontoFactory; @DisplayName("Parse formData") @Nested @@ -119,7 +119,7 @@ class FormSolutionsHeaderMapperTest { void shouldCallServiceKontoBuildHelper() { buildFormHeader(); - verify(serviceKontoBuildHelper).buildOsiServiceKonto(any()); + verify(serviceKontoFactory).buildOsiServiceKonto(any()); } @Test @@ -128,7 +128,7 @@ class FormSolutionsHeaderMapperTest { mapper.buildFormHeader(formDataWithoutPostkorbHandle); - verify(serviceKontoBuildHelper, never()).buildOsiServiceKonto(any()); + verify(serviceKontoFactory, never()).buildOsiServiceKonto(any()); } } diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapperTest.java deleted file mode 100644 index 56b515e083af42c3b22fc050990df4765832a277..0000000000000000000000000000000000000000 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapperTest.java +++ /dev/null @@ -1,122 +0,0 @@ -package de.ozgcloud.eingang.semantik.enginebased.xta; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.io.InputStream; -import java.util.List; -import java.util.stream.IntStream; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.Spy; - -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.semantik.common.ZipAttachmentReader; -import lombok.SneakyThrows; - -class XtaZipRepresentationsMapperTest { - - private static final String ZIP_CONTENT_TYPE = "application/zip"; - - @Spy - private final XtaZipRepresentationsMapper mapper = new XtaZipRepresentationsMapper(); - - @Nested - class TestExtractZipFileEctract { - - @Test - void shouldExtractZipFiles() { - try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) { - initZipRepresentationMocks(zipAttachment); - - var formData = mapper.parseFormData(createTestFormDataWithZipRepresentation()); - - assertThat(formData.getRepresentations()).hasSize(3); - } - } - - FormData createTestFormDataWithZipRepresentation() { - List<IncomingFile> representations = List.of( - IncomingFileTestFactory.createBuilder() - .name("attachments.zip") - .contentType(ZIP_CONTENT_TYPE) - .build()); - - return FormData.builder().representations(representations).numberOfRepresentations(representations.size()).build(); - } - - @Test - void shouldSetRepresentationsNumber() { - try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) { - initZipRepresentationMocks(zipAttachment); - - var formData = mapper.parseFormData(createTestFormDataWithZipRepresentation()); - - assertThat(formData.getNumberOfRepresentations()).isEqualTo(3); - } - } - - @Test - void shouldIgnoreNonZipFiles() { - try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) { - - var formData = mapper.parseFormData(createTestFormDataWithoutZipRepresentation()); - - assertThat(formData.getNumberOfRepresentations()).isEqualTo(1); - } - } - - FormData createTestFormDataWithoutZipRepresentation() { - List<IncomingFile> representations = List.of( - IncomingFileTestFactory.create()); - return FormData.builder().representations(representations).numberOfRepresentations(representations.size()).build(); - } - - @Test - void shouldNotDeleteOriginalZipFile() { - try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) { - initZipRepresentationMocks(zipAttachment); - - var formData = mapper.parseFormData(createTestFormDataWithZipRepresentation()); - - assertThat(formData.getRepresentations()).map(IncomingFile::getContentType) - .filteredOn(e -> e.equals(XtaZipRepresentationsMapper.ZIP_CONTENT_TYPE)).hasSize(1); - } - } - - @Test - void shouldDoNothingOnEmptyRepresentations() { - try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) { - - var formData = mapper.parseFormData(createTestFormDataWithoutRepresentation()); - - assertThat(formData.getRepresentations()).isEmpty(); - } - } - - FormData createTestFormDataWithoutRepresentation() { - return FormData.builder().numberOfRepresentations(0).build(); - } - } - - @Test - void testIsZipFilePredicate() { - - assertThat(XtaZipRepresentationsMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.create())).isFalse(); - assertThat(XtaZipRepresentationsMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.createBuilder().contentType(ZIP_CONTENT_TYPE).build())) - .isTrue(); - } - - @SneakyThrows - private static void initZipRepresentationMocks(MockedStatic<ZipAttachmentReader> zipAttachmentMock) { - var contentEntries = IntStream.range(0, 2).boxed().map(i -> IncomingFileTestFactory.createBuilder().name(i.toString()).build()).toList(); - ZipAttachmentReader mock = when(mock(ZipAttachmentReader.class).readContent()).thenReturn(contentEntries).getMock(); - zipAttachmentMock.when(() -> ZipAttachmentReader.from(any(InputStream.class), any())).thenReturn(mock); - } -} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java index b5d93dca98b934def05ddc44663222dfc9484b9d..7cb39b39ea3e1a7be01f3e256eb8a607724118f6 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java @@ -39,8 +39,6 @@ import org.mockito.Spy; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; -import de.ozgcloud.eingang.semantik.formbased.FormBasedMapper; -import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter; class FormBasedSemantikAdapterTest { @@ -71,7 +69,7 @@ class FormBasedSemantikAdapterTest { } @Test - void shouldNotCallMappersIfNOTREsponsible() { + void shouldNotCallMapperIfNotResponsible() { when(mapper.isResponsible(any())).thenReturn(false); adapter.parseFormData(formData); @@ -89,4 +87,4 @@ class FormBasedSemantikAdapterTest { assertThat(result).isSameAs(expected); } } -} \ 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 new file mode 100644 index 0000000000000000000000000000000000000000..9d2094d600c3eed7495003e5dfa9ba969a9b4599 --- /dev/null +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java @@ -0,0 +1,101 @@ +package de.ozgcloud.eingang.semantik.formbased.mantelantrag; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.ActiveProfiles; + +import de.ozgcloud.common.binaryfile.TempFileUtils; +import de.ozgcloud.common.test.TestUtils; +import de.ozgcloud.eingang.Application; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.router.VorgangService; +import de.ozgcloud.eingang.semantik.SemantikAdapter; +import de.ozgcloud.eingang.semantik.enginebased.formsolutions.FormSolutionsEngineBasedAdapterITCase; +import lombok.SneakyThrows; + +@ActiveProfiles({ "local", "itcase" }) +@SpringBootTest(classes = Application.class, properties = { "ozgcloud.xta.identifier=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"; + private static final String FILE_NAME_MANTELANTRAG = "mantelantrag/4620-EH6C_7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml"; + + @MockBean + VorgangService vorgangService; + + @SpyBean + SemantikAdapter semantikAdapter; + + @Nested + class TestZustaendigeStelle { + + @Captor + ArgumentCaptor<FormData> formDataCaptor; + + @Test + void zustaendigeStelleExists() { + var formData = prepareTestData(); + doReturn("test").when(vorgangService).createVorgang(any(FormData.class)); + semantikAdapter.processFormData(formData); + + verify(vorgangService).createVorgang(formDataCaptor.capture()); + FormData capturedFormData = formDataCaptor.getValue(); + assertThat(capturedFormData).isNotNull(); + } + + @Test + void zustaendigeStelleIsUtopia() { + var formData = prepareTestData(); + doReturn("test").when(vorgangService).createVorgang(any(FormData.class)); + semantikAdapter.processFormData(formData); + + verify(vorgangService).createVorgang(formDataCaptor.capture()); + FormData capturedFormData = formDataCaptor.getValue(); + + assertThat(capturedFormData.getZustaendigeStelle().getOrganisationseinheitenId()).isEqualTo("123"); + } + + } + + private FormData prepareTestData() { + var xdomeaFile = IncomingFileTestFactory.createBuilder() + .name(FILE_NAME_XDOMEA) + .file(asFile(FILE_NAME_XDOMEA)) + .size(getFileSize(FILE_NAME_XDOMEA)) + .contentType("application/xml") + .build(); + var mantelantragFile = IncomingFileTestFactory.createBuilder() + .name(FILE_NAME_MANTELANTRAG) + .file(asFile(FILE_NAME_MANTELANTRAG)) + .size(getFileSize(FILE_NAME_MANTELANTRAG)) + .contentType("application/xml") + .build(); + + return FormData.builder().representations(List.of(xdomeaFile, mantelantragFile)).build(); + } + + @SneakyThrows + private long getFileSize(String fileName) { + Path filePath = Path.of(FormSolutionsEngineBasedAdapterITCase.class.getClassLoader().getResource(fileName).toURI()); + return Files.size(filePath); + } + + private File asFile(String path) { + return TempFileUtils.writeTmpFile(TestUtils.loadFile(path)); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..f03169a6704aae741e3234b82aff876448b027d6 --- /dev/null +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java @@ -0,0 +1,331 @@ +package de.ozgcloud.eingang.semantik.formbased.mantelantrag; + +import static de.ozgcloud.eingang.semantik.formbased.mantelantrag.MantelantragZustaendigeStelleMapper.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +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.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.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; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; + +class MantelantragZustaendigeStelleMapperTest { + private final static String TARGET_OEID = "123456"; + private static final String IDENTIFIER = "gea:test"; + + @Spy + @InjectMocks + private MantelantragZustaendigeStelleMapper mapper; + + @Mock + private Environment environment; + + @DisplayName("is responsible") + @Nested + class TestIsResponsible { + + @DisplayName("should be true if mantelantrag starts with form id") + @ParameterizedTest + @ValueSource(strings = { MANTELANTRAG_FORM_ID, MANTELANTRAG_FORM_ID + "_pvog" }) + void shouldBeTrueIfMantelantragStartsWithFormId(String formId) { + var formData = createWithFormId(formId); + + var isResponsibleResult = mapper.isResponsible(formData); + + assertThat(isResponsibleResult).isTrue(); + } + + @DisplayName("should be false if not mantelantrag form id") + @Test + void shouldBeFalseIfNotMantelantragFormId() { + var formData = createWithFormId("any other id"); + + var isResponsibleResult = mapper.isResponsible(formData); + + assertThat(isResponsibleResult).isFalse(); + } + + @DisplayName("should be false if header null") + @Test + void shouldBeFalseIfHeaderNull() { + var formData = FormDataTestFactory.createBuilder() + .header(null) + .build(); + + var isResponsibleResult = mapper.isResponsible(formData); + + assertThat(isResponsibleResult).isFalse(); + } + + @DisplayName("should be false if form id null") + @Test + void shouldBeFalseIfFormIdNull() { + var formData = FormDataTestFactory.createBuilder() + .header(FormHeaderTestFactory.createBuilder() + .formId(null) + .build()) + .build(); + + var isResponsibleResult = mapper.isResponsible(formData); + + assertThat(isResponsibleResult).isFalse(); + } + + private FormData createWithFormId(String formId) { + return FormDataTestFactory.createBuilder() + .header(FormHeaderTestFactory.createBuilder() + .formId(formId) + .build()) + .build(); + } + } + + @DisplayName("adapt form data") + @Nested + class TestAdaptFormData { + + @Mock + private FormData formData; + + @Mock + private FormData formData2; + + @DisplayName("should return adapted value") + @Test + void shouldReturnAdaptedValue() { + doReturn(formData2).when(mapper).adaptFormDataWithPossibleException(formData); + + var resultFormData = mapper.parseFormData(formData); + + assertThat(resultFormData).isEqualTo(formData2); + } + + @DisplayName("should return original value with exception") + @Test + void shouldReturnOriginalValueWithException() { + doThrow(new TechnicalException("some error")).when(mapper).adaptFormDataWithPossibleException(formData); + + var resultFormData = mapper.parseFormData(formData); + + assertThat(resultFormData).isEqualTo(formData); + } + } + + @DisplayName("adapt form data with possible exception") + @Nested + class TestAdaptFormDataWithPossibleException { + + static final String TARGET_OPTIONAL_FIELD_VALUE = "optionalFieldValue"; + static final Map<String, Function<ZustaendigeStelle, String>> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR = Map.of( + BEZEICHNUNG_FIELD, ZustaendigeStelle::getBezeichnung, + EMAIL_FIELD, ZustaendigeStelle::getEmail, + HAUSANSCHRIFT_STRASSE_FIELD, ZustaendigeStelle::getHausanschriftStrasse, + HAUSANSCHRIFT_PLZ_FIELD, ZustaendigeStelle::getHausanschriftPlz, + HAUSANSCHRIFT_ORT_FIELD, ZustaendigeStelle::getHausanschriftOrt, + TELEFON_FIELD, ZustaendigeStelle::getTelefon + ); + private FormData formData; + private Map<String, Object> fieldMap; + + private static Stream<Arguments> fieldNameAndSlotIndex() { + return Stream.of(0, 1, 2) + .flatMap(slotIndex -> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR + .keySet().stream() + .map(fieldName -> Arguments.of(slotIndex, fieldName)) + ); + } + + @BeforeEach + void mock() { + fieldMap = new HashMap<>(Map.of( + getOrganisationseinheitIDFieldName(1), " ", + getOrganisationseinheitIDFieldName(2), "", + getOrganisationseinheitIDFieldName(10), "1111111" + )); + formData = FormDataTestFactory.createBuilder() + .formData(fieldMap) + .build(); + } + + @DisplayName("should keep form data except zustaendigestelle") + @Test + void shouldKeepFormDataExceptZustaendigestelle() { + doReturn(10).when(mapper).findSlotIndex(fieldMap); + + var resultFormData = mapper.parseFormData(formData); + + assertThat(resultFormData.getId()).isEqualTo(formData.getId()); + assertThat(resultFormData.getHeader()).isEqualTo(formData.getHeader()); + assertThat(resultFormData.getAntragsteller()).isEqualTo(formData.getAntragsteller()); + } + + @DisplayName("should map organisationseinheitId") + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2 }) + void shouldMapOrganisationseinheitId(int slotIndex) { + mockWithOEID(slotIndex, TARGET_OEID); + + var zustaendigeStelle = getAdaptedZustaendigeStelle(); + + assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(TARGET_OEID); + } + + private String getOrganisationseinheitIDFieldName(int slotIndex) { + return mapper.getNameForSlotIndex(ORGANISATIONSEINHEIT_ID_FIELD, slotIndex); + } + + @DisplayName("should throw if organistaionseinheitId is missing") + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2 }) + void shouldThrowIfOrganistationseinheitIdIsMissing(int slotIndex) { + doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap); + + assertThatThrownBy(this::getAdaptedZustaendigeStelle) + .isInstanceOf(TechnicalException.class); + } + + @DisplayName("should throw if organistationseinheitId is empty") + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2 }) + void shouldThrowIfOrganistationseinheitIdIsEmpty(int slotIndex) { + mockWithOEID(slotIndex, ""); + + assertThatThrownBy(this::getAdaptedZustaendigeStelle) + .isInstanceOf(TechnicalException.class); + } + + @DisplayName("should map optional field") + @ParameterizedTest + @MethodSource("fieldNameAndSlotIndex") + void shouldMapOptionalField(int slotIndex, String fieldName) { + mockWithSomeOEID(slotIndex); + fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), TARGET_OPTIONAL_FIELD_VALUE); + + var zustaendigeStelle = getAdaptedZustaendigeStelle(); + + assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEqualTo(TARGET_OPTIONAL_FIELD_VALUE); + } + + @DisplayName("should map missing optional fields to empty") + @ParameterizedTest + @MethodSource("fieldNameAndSlotIndex") + void shouldMapMissingOptionalFieldsToEmpty(int slotIndex, String fieldName) { + mockWithSomeOEID(slotIndex); + + var zustaendigeStelle = getAdaptedZustaendigeStelle(); + + assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty(); + } + + @DisplayName("should map empty optional fields to empty") + @ParameterizedTest + @MethodSource("fieldNameAndSlotIndex") + void shouldMapEmptyOptionalFieldsToEmpty(int slotIndex, String fieldName) { + mockWithSomeOEID(slotIndex); + fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), ""); + + var zustaendigeStelle = getAdaptedZustaendigeStelle(); + + assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty(); + } + + private String getExpectedByFieldName(ZustaendigeStelle zustaendigeStelle, String fieldName) { + var valueExtractor = FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR.get(fieldName); + return valueExtractor.apply(zustaendigeStelle); + } + + private void mockWithSomeOEID(int slotIndex) { + mockWithOEID(slotIndex, "some"); + } + + private void mockWithOEID(int slotIndex, String targetOeid) { + fieldMap.put(getOrganisationseinheitIDFieldName(slotIndex), targetOeid); + doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap); + } + + private ZustaendigeStelle getAdaptedZustaendigeStelle() { + var formDataResult = mapper.adaptFormDataWithPossibleException(formData); + return formDataResult.getZustaendigeStelle(); + } + + } + + @DisplayName("find slot index") + @Nested + class TestFindSlotIndex { + + private Map<String, Object> fieldMap; + + @BeforeEach + void mock() { + when(environment.getProperty("ozgcloud.xta.identifier")).thenReturn(IDENTIFIER); + + fieldMap = new HashMap<>(Map.of( + getZustaendigeStelleName(1), "unknown", + getZustaendigeStelleName(2), "" + )); + } + + @DisplayName("should return matching slot") + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2 }) + void shouldReturnMatchingSlot(int slotIndex) { + fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER); + + var resultSlotIndex = mapper.findSlotIndex(fieldMap); + + assertThat(resultSlotIndex).isEqualTo(slotIndex); + } + + private String getZustaendigeStelleName(int slotIndex) { + return mapper.getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex); + } + + @DisplayName("should throw if no slot matches") + @Test + void shouldThrowIfNoSlotMatches() { + assertThatThrownBy(() -> mapper.findSlotIndex(fieldMap)) + .isInstanceOf(TechnicalException.class); + } + } + + @DisplayName("get name for slot index") + @Nested + class TestGetNameForSlotIndex { + private static Stream<Arguments> nameAndSlotIndexAndExpected() { + return Stream.of( + Arguments.of("name", 0, "name"), + Arguments.of("name", 1, "name2"), + Arguments.of("name", 2, "name3") + ); + } + + @DisplayName("should return name") + @ParameterizedTest + @MethodSource("nameAndSlotIndexAndExpected") + void shouldReturnName(String name, int slotIndex, String expected) { + var resultName = mapper.getNameForSlotIndex(name, slotIndex); + + assertThat(resultName).isEqualTo(expected); + } + } +} diff --git a/semantik-adapter/src/test/resources/A12/a12FormData.json b/semantik-adapter/src/test/resources/A12/a12FormData.json new file mode 100644 index 0000000000000000000000000000000000000000..5b93978371da34f8de9145c444e0c9225e2debce --- /dev/null +++ b/semantik-adapter/src/test/resources/A12/a12FormData.json @@ -0,0 +1,16 @@ +{ + "root": { + "Haushaltsjahr": "2024", + "Anlage_2": { + "Finanzierungsplan": { + "Insgesamt_Finanzierungsplan": 117450, + "Eigenmittel_von_Hundert": 1.5, + "Erlaeuterungen_Finanzierungsplan": "Das passt doch schon so.", + "Zuwendung_kommunale": { + "Gemeinden": "Eselstadt", + "Zuwendung_Gemeinden": 100000 + } + } + } + } +} \ No newline at end of file diff --git a/semantik-adapter/src/test/resources/formsolutions/attachment-2files.zip b/semantik-adapter/src/test/resources/formsolutions/attachment-2files.zip new file mode 100644 index 0000000000000000000000000000000000000000..1cd6370639e85040002e6b17df7dc2c36b877673 Binary files /dev/null and b/semantik-adapter/src/test/resources/formsolutions/attachment-2files.zip differ diff --git a/intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml b/semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml rename to semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml b/semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml rename to semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml b/semantik-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml rename to semantik-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml b/semantik-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml rename to semantik-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml rename to semantik-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml b/semantik-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml rename to semantik-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml diff --git a/intelliform-adapter/src/test/resources/intelliform/andererName-Daten.xml b/semantik-adapter/src/test/resources/intelliform/andererName-Daten.xml similarity index 100% rename from intelliform-adapter/src/test/resources/intelliform/andererName-Daten.xml rename to semantik-adapter/src/test/resources/intelliform/andererName-Daten.xml diff --git a/semantik-adapter/src/test/resources/mantelantrag/4620-EH6C_7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml b/semantik-adapter/src/test/resources/mantelantrag/4620-EH6C_7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml new file mode 100644 index 0000000000000000000000000000000000000000..dfe5df9a75784d09bed9a8b2d7a6506822906f0f --- /dev/null +++ b/semantik-adapter/src/test/resources/mantelantrag/4620-EH6C_7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="UTF-8"?> +<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" + xmlns:u="http://xmlns.cit.de/intelliform/user" t:uuid="87812a84-a463-4922-b8dd-f1d0d7c5f0d7" + t:id="20240620346740905800" + t:timestamp="2024-06-20T07:37:54.042Z" + t:sender="stage.afm.schleswig-holstein.de" + t:form="Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe" + t:form-id="maa_mantelantrag/maa_mantelantrag" t:customer="Schleswig-Holstein" + t:customer-id="sh" t:client="Schleswig-Holstein" t:client-id="land" t:lang="de" + u:FamilyNames="Bolay" u:PrincipalType="Citizen" u:Username="joerg.bolay@dataport.de" + u:CitizenProfileType="Standard" u:username="605b5b10-0c3c-4b2d-247c-08da6f152b74" u:GivenNames="Jörg" + u:AssuranceLevel="Low" u:Title="Herr" u:displayName="Jörg Bolay" u:mailAddress="joerg.bolay@dataport.de" + u:EmailAddress="joerg.bolay@dataport.de" u:firstName="Jörg" u:lastName="Bolay" t:required-login-level="LOW" + t:effective-login-level="LOW"> + <gebiets_id>9007404</gebiets_id> + <egh_sgb9>false</egh_sgb9> + <hzl>false</hzl> + <grusi>false</grusi> + <hzg>false</hzg> + <hzp>true</hzp> + <ambulant_stationaer>ambulant</ambulant_stationaer> + <hzuebss>false</hzuebss> + <hial>false</hial> + <ambulant>true</ambulant> + <stationaer>false</stationaer> + <sessionid>e898afa9-6f12-49f9-85fc-b52b86492640</sessionid> + <anliegen_id>[8936847]</anliegen_id> + <anliegen_namen>[Ambulante Hilfe zur Pflege]</anliegen_namen> + <TypenIDLN>233034601</TypenIDLN> + <logopath1/> + <logopath2/> + <logopath3/> + <gebiet_typid>300004</gebiet_typid> + <gebiet_parent_id1>9006398</gebiet_parent_id1> + <gebiet_parent_typid1>300003</gebiet_parent_typid1> + <gebiet_parent_id2>9006398</gebiet_parent_id2> + <gebiet_parent_typid2>300003</gebiet_parent_typid2> + <gebiet_parent_id3>9006398</gebiet_parent_id3> + <gebiet_parent_typid3>300003</gebiet_parent_typid3> + <gebiet_parent_name3>Segeberg</gebiet_parent_name3> + <oeid>[266235917]</oeid> + <link_datenschutz>https://www.segeberg.de/datenschutz</link_datenschutz> + <link_datenschutz2/> + <link_datenschutz3/> + <link_bankgeheimnis> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_Befreiung_vom_Bankgeheimnis.pdf + </link_bankgeheimnis> + <link_grundsicherung> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Erklaerung_zur_Zahlung_von_Grundsicherungsleistungen_an_Leistungserbringer.pdf + </link_grundsicherung> + <link_schweigepflicht> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Schweigepflichtentbindung.pdf + </link_schweigepflicht> + <link_abtretung> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Einverstaendniserklaerung_und_Abtretung.pdf + </link_abtretung> + <link_wahrheit> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_der_antragstellenden_Person.pdf + </link_wahrheit> + <kontaktsystem_oeid>123</kontaktsystem_oeid> + <OrganisationseinheitenBEZEICHNUNG>Kreis Segeberg - Soziale Sicherung</OrganisationseinheitenBEZEICHNUNG> + <zust_strasse>Hamburger Straße</zust_strasse> + <zust_hausnummer>30</zust_hausnummer> + <zust_postleitzahl>23795</zust_postleitzahl> + <ortid>9007404</ortid> + <zust_ort>Bad Segeberg</zust_ort> + <zust_telefonnummer>+49 4551 9519438</zust_telefonnummer> + <zust_faxnummer/> + <zust_emailadresse>sozialplanung@segeberg.de</zust_emailadresse> + <zustellung_nachrichtenbroker>afmsh:ozg-cloud-utopia-test</zustellung_nachrichtenbroker> + <zustellung_email_ln/> + <zustellung_webservice/> + <kontaktsystem_oeid2>321</kontaktsystem_oeid2> + <OrganisationseinheitenBEZEICHNUNG2/> + <zust_strasse2/> + <zust_hausnummer2/> + <zust_postleitzahl2/> + <ortid2/> + <zust_ort2/> + <zust_telefonnummer2/> + <zust_faxnummer2/> + <zust_emailadresse2/> + <zustellung_nachrichtenbroker2>afmsh:ozg-cloud-bad-segeberg-kreis</zustellung_nachrichtenbroker2> + <zustellung_email_ln2/> + <zustellung_webservice2/> + <kontaktsystem_oeid3/> + <OrganisationseinheitenBEZEICHNUNG3/> + <zust_strasse3/> + <zust_hausnummer3/> + <zust_postleitzahl3/> + <ortid3/> + <zust_ort3/> + <zust_telefonnummer3/> + <zust_faxnummer3/> + <zust_emailadresse3/> + <zustellung_nachrichtenbroker3/> + <zustellung_email_ln3/> + <zustellung_webservice3/> + <grund>Hilfe</grund> + <ambulante_hilfen>Hilfe</ambulante_hilfen> + <nur_egh>false</nur_egh> + <nur_blindenhilfe>false</nur_blindenhilfe> + <nur_pers_angaben>false</nur_pers_angaben> + <nur_pers_mehrbedarfe>false</nur_pers_mehrbedarfe> + <antragsteller> + <anrede/> + <titel/> + <pers_nachname>Mustermann</pers_nachname> + <geburtsname/> + <pers_vorname>Max</pers_vorname> + <geburtsdatum>2000-01-15</geburtsdatum> + <geburtsort/> + <sh_strasse>Musterstrasse</sh_strasse> + <sh_hausnummer>123</sh_hausnummer> + <adresszusatz/> + <sh_plz>23795</sh_plz> + <ort>Bad Segeberg</ort> + <kont_email/> + <telefon/> + <mobiltelefon/> + <familienstand>ledig</familienstand> + <deutsch>deutsch</deutsch> + <a_ausweisdokument>false</a_ausweisdokument> + <erwerb/> + <erwerbsunfaehig/> + <betreuer>false</betreuer> + <partner>false</partner> + <kont_telefonnummer/> + </antragsteller> + <angaben_antragsteller> + <sozialhilfe_p>Nein</sozialhilfe_p> + <eingliederungshilfe>Nein</eingliederungshilfe> + <leistungen/> + <rentenantrag/> + <rentenbeitraege/> + <auslandserwerb/> + <lebensunterhalt>Arbeit</lebensunterhalt> + <zuzug>false</zuzug> + <pflege_noetig>false</pflege_noetig> + <haushaltshilfe_noetig/> + <pflegesachleistung_noetig/> + <pflegegeld_noetig/> + <pflegeleistungen_noetig/> + <ansprueche_dritte>false</ansprueche_dritte> + <stoerung_vorhanden>false</stoerung_vorhanden> + <sozialhilfe>Nein</sozialhilfe> + </angaben_antragsteller> + <weitere_personen>false</weitere_personen> + <familienangehoerige>false</familienangehoerige> + <fin_antragsteller> + <groesse_wohnung unit="m2"/> + <untervermietet_wohnung unit="m2"/> + <raeume/> + <baujahr/> + <wohnung_kosten unit="Euro"/> + <betriebskosten unit="Euro"/> + <heizkosten unit="Euro"/> + <heizart/> + <a_mietvertrag>false</a_mietvertrag> + <pauschalmiete unit="Euro"/> + <warmwasser/> + <wohngeld/> + </fin_antragsteller> + <ver> + <ver-item> + <name_id>a</name_id> + <versicherung_vorhanden>false</versicherung_vorhanden> + <name>Max Mustermann</name> + <fruehere_kv_vorhanden/> + <frueherer_erwerb_v/> + <bedarf_hzg/> + <kuenftige_kv/> + </ver-item> + </ver> + <mehr> + <mehr-item> + <name_id>a</name_id> + <schwanger/> + <alleinerziehend/> + <teure_ernaehrung/> + <mittagsverpflegung/> + <schulbuecher/> + <sonderbedarf/> + <name>Max Mustermann</name> + </mehr-item> + </mehr> + <einkommen_xii> + <einkommen_xii-item> + <name_id>a</name_id> + <nselbststaendig_vorhanden>false</nselbststaendig_vorhanden> + <gewerbe_vorhanden>false</gewerbe_vorhanden> + <landwirtschaft_vorhanden>false</landwirtschaft_vorhanden> + <vermietung_vorhanden>false</vermietung_vorhanden> + <kapital_vorhanden>false</kapital_vorhanden> + <krankenkasse_vorhanden>false</krankenkasse_vorhanden> + <pflegekasse_vorhanden>false</pflegekasse_vorhanden> + <bg_vorhanden>false</bg_vorhanden> + <alg_vorhanden>false</alg_vorhanden> + <leistungen_afa_vorhanden>false</leistungen_afa_vorhanden> + <grusi_vorhanden>false</grusi_vorhanden> + <kindergeld_vorhanden>false</kindergeld_vorhanden> + <elterngeld_vorhanden>false</elterngeld_vorhanden> + <rente_inland_vorhanden>false</rente_inland_vorhanden> + <rente_ausland_vorhanden>false</rente_ausland_vorhanden> + <rente_sonstige_vorhanden>false</rente_sonstige_vorhanden> + <unterhalt_vorhanden>false</unterhalt_vorhanden> + <bafoeg_vorhanden>false</bafoeg_vorhanden> + <baukindergeld_vorhanden>false</baukindergeld_vorhanden> + <blindengeld_vorhanden>false</blindengeld_vorhanden> + <vwl_vorhanden>false</vwl_vorhanden> + <sonstiges_vorhanden>false</sonstiges_vorhanden> + <einkommen_gepfaendet>false</einkommen_gepfaendet> + <einkommen_vorhanden>false</einkommen_vorhanden> + <name>Max Mustermann</name> + </einkommen_xii-item> + </einkommen_xii> + <vermoegen> + <vermoegen-item> + <name_id>a</name_id> + <bargeld_vorhanden>false</bargeld_vorhanden> + <konto_vorhanden>false</konto_vorhanden> + <sparguthaben_vorhanden>false</sparguthaben_vorhanden> + <altersvorsorge_vorhanden>false</altersvorsorge_vorhanden> + <bausparvertraege_vorhanden>false</bausparvertraege_vorhanden> + <aktien_vorhanden>false</aktien_vorhanden> + <paypal_vorhanden>false</paypal_vorhanden> + <lebensversicherung_vorhanden>false</lebensversicherung_vorhanden> + <kfz_vorhanden>false</kfz_vorhanden> + <sachwerte_vorhanden>false</sachwerte_vorhanden> + <haus_vorhanden>false</haus_vorhanden> + <hypotheken_vorhanden>false</hypotheken_vorhanden> + <erbschaft_vorhanden>false</erbschaft_vorhanden> + <sonstiges_vorhanden>false</sonstiges_vorhanden> + <veraeusserung_vermoegen>false</veraeusserung_vermoegen> + <vermoegen_vorhanden>false</vermoegen_vorhanden> + <name>Max Mustermann</name> + </vermoegen-item> + </vermoegen> + <datenerhebung>true</datenerhebung> + <vollstaendigkeit>true</vollstaendigkeit> + <a_befreiung_bankgeheimnis>false</a_befreiung_bankgeheimnis> + <a_entbindung_schweigepflicht>false</a_entbindung_schweigepflicht> + <name_bank/> + <iban/> + <kontoinhaber/> + <name_pdf>Antrag_Max_Mustermann_SGBXII</name_pdf> + <postfachnachicht>Sehr geehrte/r Antragsteller*in,<br/><br/>Ihr Antrag wurde erfolgreich übermittelt.<br/><br/>Bitte + denken Sie daran, zur Vervollständigung Ihres Antrages die unterschriebenen Dokumente und erforderlichen + Nachweise einzureichen.<br/><br/>Die Bearbeitung Ihres Antrages ist erst nach Vorlage aller + erforderlichen Dokumente und Nachweise möglich.<br/><br/><br/>Mit freundlichen Grüßen<br/><br/>Kreis + Segeberg - Soziale Sicherung<br/>Hamburger Straße 30<br/>23795 Bad Segeberg + </postfachnachicht> +</myForm> \ No newline at end of file diff --git a/semantik-adapter/src/test/resources/mantelantrag/4620-EH6C_b3c9168a-6ae9-4361-8b2f-6837bb341021_Geschaeftsgang.Geschaeftsgang.0201.xml b/semantik-adapter/src/test/resources/mantelantrag/4620-EH6C_b3c9168a-6ae9-4361-8b2f-6837bb341021_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..6054acb59996d3a71da066dc3bd6956506c35460 --- /dev/null +++ b/semantik-adapter/src/test/resources/mantelantrag/4620-EH6C_b3c9168a-6ae9-4361-8b2f-6837bb341021_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,125 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>b3c9168a-6ae9-4361-8b2f-6837bb341021</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Nachrichtentyp">0201</xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-06-20T09:55:04.420+02:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Schleswig-Holstein</xdomea:Name> + <xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-utopia-test">ozg-cloud-utopia-test</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>4e31a750-4988-48f6-928e-066c98238173</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe</xdomea:Betreff> + <xdomea:Kennzeichen>20240620346740905800</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-06-20</xdomea:Posteingangsdatum> + <xdomea:Typ>maa_mantelantrag/maa_mantelantrag</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + <xdomea:Version> + <xdomea:Nummer>0.0</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>90c53ff4-259b-4165-8ad3-9dda32235ca2_Antrag_Max_Mustermann_SGBXII.pdf</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>69f5c99d-8f53-448a-b800-cf165d40392e</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001</xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-utopia-test">ozg-cloud-utopia-test</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-06-20</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>09:55:03</xdomea:Erstellungsuhrzeit> + </xdomea:Verfuegung> + </xdomea:Beteiligungsschritt> + </xdomea:ExternerGeschaeftsgang> + <xdomea:Anlage> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>9c0d0202-f193-47e6-bd3e-f230b240c41b</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>799220b6-df8a-482c-a451-62916a558b1a_SAML-Assertion.xml</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Anlage> + <xdomea:Anlage> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>fa8c3b9e-db49-4094-bb2e-09ea4557f1d1</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>aeb3e272-de0d-46b4-9340-6358035facea_EmailBodyBuergerTemplate.xml</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Anlage> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201> \ No newline at end of file diff --git a/src/main/helm/templates/bindings_type_configmap.yaml b/src/main/helm/templates/bindings_type_configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8e4fbacefd484339668748edd53d0f4503a14ac5 --- /dev/null +++ b/src/main/helm/templates/bindings_type_configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-bindings-type + namespace: {{ include "app.namespace" . }} +data: + type: | + ca-certificates \ No newline at end of file diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml index c7e9bcd8833a52f0e9f1bd7d747ccaadcaf971f3..b3bfd90e14e00c464ea72646affc1408ee4f9923 100644 --- a/src/main/helm/templates/deployment.yaml +++ b/src/main/helm/templates/deployment.yaml @@ -59,6 +59,8 @@ spec: app.kubernetes.io/name: {{ .Release.Name }} containers: - env: + - name: SERVICE_BINDING_ROOT + value: "/bindings" {{- range (.Values.env).grpc }} - name: {{ .name }} value: {{ .value }} @@ -79,7 +81,7 @@ spec: - name: grpc_client_vorgang-manager-{{ (.Values.routing).targetVorgangManagerName}}_address value: 'vorgang-manager.{{ coalesce (.Values.routing).targetNamespace .Release.Namespace }}:9090' - name: grpc_client_vorgang-manager-{{ (.Values.routing).targetVorgangManagerName}}_negotiationType - value: {{ (.Values.routing).negotiationType | default "PLAINTEXT" }} + value: {{ (.Values.routing).negotiationType | default "TLS" }} {{- end }} {{- with include "app.getCustomList" . }} {{ . | indent 8 }} @@ -150,9 +152,23 @@ spec: volumeMounts: - name: temp-dir mountPath: "/tmp" + - name: namespace-ca-cert + mountPath: "/bindings/namespace-certificate" + readOnly: true volumes: - name: temp-dir emptyDir: {} + - name: namespace-ca-cert + projected: + sources: + - secret: + name: {{ include "app.namespace" . }}-ca-cert + optional: true + items: + - key: ca.crt + path: ca.crt + - configMap: + name: {{ .Release.Name }}-bindings-type dnsConfig: {} dnsPolicy: ClusterFirst imagePullSecrets: diff --git a/src/test/helm/bindings_type_test.yaml b/src/test/helm/bindings_type_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f0fa5ade329232c346f328205e67e54f03e1f262 --- /dev/null +++ b/src/test/helm/bindings_type_test.yaml @@ -0,0 +1,46 @@ +# +# Copyright (C) 2022 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. +# + +suite: test bindings type configmap +templates: + - templates/bindings_type_configmap.yaml +release: + name: eingang-manager + namespace: sh-helm-test +tests: + - it: xta bindings type + asserts: + - isKind: + of: ConfigMap + - isAPIVersion: + of: v1 + - equal: + path: metadata.name + value: eingang-manager-bindings-type + - equal: + path: metadata.namespace + value: sh-helm-test + - equal: + path: data.type + value: ca-certificates diff --git a/src/test/helm/deployment_bindings_test.yaml b/src/test/helm/deployment_bindings_test.yaml index 6e48055b01e611b36369c432835f085bebc69b3c..f4e0f24ea4f4e017b21eb33eb0f331ca415a6346 100644 --- a/src/test/helm/deployment_bindings_test.yaml +++ b/src/test/helm/deployment_bindings_test.yaml @@ -25,6 +25,9 @@ suite: deployment bindings templates: - templates/deployment.yaml +release: + name: eingang-manager + namespace: sh-helm-test set: ozgcloud.environment: test imagePullSecret: image-pull-secret @@ -45,3 +48,28 @@ tests: name: temp-dir emptyDir: {} + - it: should have projected namespace-ca-cert volume + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: namespace-ca-cert + projected: + sources: + - secret: + name: sh-helm-test-ca-cert + optional: true + items: + - key: ca.crt + path: ca.crt + - configMap: + name: eingang-manager-bindings-type + + - it: should have namespace-ca-cert volume mount + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: namespace-ca-cert + mountPath: "/bindings/namespace-certificate" + readOnly: true \ No newline at end of file diff --git a/src/test/helm/deployment_routing_strategy_env.yaml b/src/test/helm/deployment_routing_strategy_env.yaml index dc9ae515b3ad4c3c4ae977d4700736ff1f6633dc..cd24633dbc3eed6ed59ccd58b70dbf4397b847a1 100644 --- a/src/test/helm/deployment_routing_strategy_env.yaml +++ b/src/test/helm/deployment_routing_strategy_env.yaml @@ -49,13 +49,13 @@ tests: path: spec.template.spec.containers[0].env content: name: grpc_client_vorgang-manager-vorgang-manager_negotiationType - value: PLAINTEXT + value: TLS - it: validate routing infos set: routing: routingStrategy: MULTI fallbackStrategy: FUNDSTELLE - negotiationType: TLS + negotiationType: PLAINTEXT asserts: - contains: path: spec.template.spec.containers[0].env @@ -71,4 +71,4 @@ tests: path: spec.template.spec.containers[0].env content: name: grpc_client_vorgang-manager-vorgang-manager_negotiationType - value: TLS \ No newline at end of file + value: PLAINTEXT \ No newline at end of file diff --git a/xta-adapter/pom.xml b/xta-adapter/pom.xml index 668a46db3edd844580fdafd5e2692d870360dd4d..f3a787bc15f6dff133b8cf13801552945ea579fe 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.8.0-SNAPSHOT</version> + <version>2.10.0-SNAPSHOT</version> </parent> <artifactId>xta-adapter</artifactId> <name>Eingangs Adapter - XTA</name> @@ -81,6 +81,13 @@ <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> + <!-- Test --> + <dependency> + <groupId>de.ozgcloud.eingang</groupId> + <artifactId>common</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/xta-adapter/readme.md b/xta-adapter/readme.md index 0bac437c660b639ce2889e763554ca4cf0850e8e..90aae87977480941270881dcddd21111a4f0ff52 100644 --- a/xta-adapter/readme.md +++ b/xta-adapter/readme.md @@ -43,3 +43,6 @@ DEPRECATED, da wir den HostNameVerifier deaktiviert haben: Hosts Datei erzeugen, 127.0.0.1 LI33-0005 +# SoapUi Projekt zum manuellen Abrufen des Nachrichtenbrokers +Im Dokumentation Repo unter `Entwicklungsumgebung/Beistellungen/soapUiXTA` liegt ein SoapUi Projekt, +dass manuelle XTA-Aufrufe des Nachrichtenbrokers ermöglicht. diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XMLHelper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XMLHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..1eb09f2e7a2fd4e6b194e855f40ea50e110dc044 --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XMLHelper.java @@ -0,0 +1,63 @@ +package de.ozgcloud.eingang.xdomea; + +import java.io.IOException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class XMLHelper { + + private static final DocumentBuilder DOCUMENT_BUILDER = createDocumentBuilder(); + private static final XPathFactory X_PATH_FACTORY = createXPathFactory(); + + public static Document parseDocument(IncomingFile incomingFile) { + try (var inputStream = incomingFile.getContentStream()) { + return DOCUMENT_BUILDER.parse(inputStream); + } catch (SAXException | IOException e) { + throw new TechnicalException("Failed to parse xml document!", e); + } + } + + public static XPathExpression compileXPathExpression(String xPathString) { + try { + return X_PATH_FACTORY.newXPath().compile(xPathString); + } catch (XPathExpressionException e) { + throw new TechnicalException("Failed to compile xpath expression!", e); + } + } + + private static DocumentBuilder createDocumentBuilder() { + var documentBuilderFactory = DocumentBuilderFactory.newInstance(); + try { + documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + return documentBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new TechnicalException("Failed to configure document builder", e); + } + } + + private static XPathFactory createXPathFactory() { + var xPathFactory = XPathFactory.newInstance(); + try { + xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + return xPathFactory; + } catch (XPathFactoryConfigurationException e) { + throw new TechnicalException("Failed to configure xpath factory!", e); + } + } +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageData.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageData.java new file mode 100644 index 0000000000000000000000000000000000000000..432b06c5273798eb5bf67ff0666dea40211c69ad --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageData.java @@ -0,0 +1,17 @@ +package de.ozgcloud.eingang.xdomea; + +import java.util.List; + +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import lombok.Builder; +import lombok.Singular; + +@Builder +public record XdomeaMessageData( + IncomingFile metadataFile, + List<IncomingFile> representations, + @Singular + List<IncomingFileGroup> attachments +) { +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e6d9f6836b5ef0d26087356de2545d512683b863 --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapper.java @@ -0,0 +1,111 @@ +package de.ozgcloud.eingang.xdomea; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.springframework.stereotype.Component; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Component +@Log4j2 +@RequiredArgsConstructor +public class XdomeaMessageDataMapper { + static final String XDOMEA_0201_XML_FILE_NAME_SUFFIX = "_Geschaeftsgang.Geschaeftsgang.0201.xml"; + static final String ATTACHMENT_GROUP_NAME = "Dokument"; + + private final XdomeaXMLValueReader valueReader; + + public XdomeaMessageData mapIncomingFilesToXdomeaMessageData(List<IncomingFile> incomingFileList) { + var xdomeaXMLFile = findXdomeaXMLFile(incomingFileList); + var representationFileNames = valueReader.readRepresentationFileNames(xdomeaXMLFile); + var attachmentFileNames = getFileNamesExcluding( + incomingFileList, + Stream.concat(Stream.of(xdomeaXMLFile.getName()), representationFileNames.stream()) + ); + + var fileNameToFileMap = createFileNameToIncomingFileMap(incomingFileList); + return XdomeaMessageData.builder() + .metadataFile(xdomeaXMLFile) + .representations(getRepresentations(representationFileNames, fileNameToFileMap)) + .attachments(getAttachments(attachmentFileNames, fileNameToFileMap)) + .build(); + } + + private Map<String, IncomingFile> createFileNameToIncomingFileMap(List<IncomingFile> incomingFileList) { + return incomingFileList.stream() + .collect(Collectors.toMap(IncomingFile::getName, file -> file)); + } + + private Stream<String> getFileNamesExcluding(List<IncomingFile> incomingFileList, Stream<String> excludedFileNames) { + return dropNames( + incomingFileList.stream().map(IncomingFile::getName), + excludedFileNames.collect(Collectors.toSet()) + ); + } + + private List<IncomingFile> getRepresentations(List<String> representationFileNames, Map<String, IncomingFile> fileNameToFileMap) { + return getFilesByName( + movePrimaryRepresentationFileNameToFirstPosition(representationFileNames), + fileNameToFileMap + ); + } + + private List<IncomingFileGroup> getAttachments(Stream<String> attachmentFileNames, Map<String, IncomingFile> fileNameToFileMap) { + return Stream.of(IncomingFileGroup.builder() + .name(ATTACHMENT_GROUP_NAME) + .files( + getFilesByName( + attachmentFileNames, + fileNameToFileMap + ) + ) + .build()) + // Do not include empty attachment group + .filter(group -> !group.getFiles().isEmpty()) + .toList(); + } + + private Stream<String> movePrimaryRepresentationFileNameToFirstPosition(List<String> representationFileNames) { + var primaryRepresentationFileName = findPrimaryRepresentationName(representationFileNames); + return Stream.concat( + Stream.of(primaryRepresentationFileName), + dropNames(representationFileNames.stream(), Set.of(primaryRepresentationFileName)) + ); + } + + private List<IncomingFile> getFilesByName(Stream<String> names, Map<String, IncomingFile> fileNameToFileMap) { + return names.map(fileNameToFileMap::get).toList(); + } + + private Stream<String> dropNames(Stream<String> names, Set<String> namesToDrop) { + return names.filter(name -> !namesToDrop.contains(name)); + } + + String findPrimaryRepresentationName(List<String> representationFileNames) { + var xmlFileNames = representationFileNames.stream() + .filter(name -> name.endsWith(".xml")) + .toList(); + if (xmlFileNames.isEmpty()) { + throw new TechnicalException("No xml representation file name found!"); + } else if (xmlFileNames.size() > 1) { + LOG.warn("There is more than one xml representations. Choosing the first of {}.", xmlFileNames.size()); + } + return xmlFileNames.getFirst(); + } + + IncomingFile findXdomeaXMLFile(List<IncomingFile> incomingFileList) { + return incomingFileList.stream() + .filter(file -> file.getName().endsWith(XDOMEA_0201_XML_FILE_NAME_SUFFIX)) + .findFirst() + .orElseThrow(() -> new TechnicalException("Primary xdomea xml representation not found!")); + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..961231e9ad05e5ef208c05f5218493ebddd0b44e --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java @@ -0,0 +1,60 @@ +package de.ozgcloud.eingang.xdomea; + +import static de.ozgcloud.eingang.xdomea.XMLHelper.*; + +import java.util.List; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; + +import org.springframework.stereotype.Component; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; + +@Component +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); + + public List<String> readRepresentationFileNames(IncomingFile xdomeaXMLFile) { + return getTextsFromNodes( + queryDateinameNodeList( + XMLHelper.parseDocument(xdomeaXMLFile) + .getDocumentElement() + ) + ); + } + + private NodeList queryDateinameNodeList(Element contextElement) { + try { + return (NodeList) DATEINAME_NODE_QUERY + .evaluate( + contextElement, + XPathConstants.NODESET + ); + } catch (XPathExpressionException e) { + throw new TechnicalException("Failed to execute xpath search!", e); + } + } + + private List<String> getTextsFromNodes(NodeList nodeList) { + return streamNodeList(nodeList) + .map(Node::getTextContent) + .map(String::trim) + .toList(); + } + + private Stream<Node> streamNodeList(NodeList nodeList) { + return IntStream.range(0, nodeList.getLength()) + .mapToObj(nodeList::item); + } + +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaApplicationConfiguration.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaApplicationConfiguration.java deleted file mode 100644 index 2b85133aa7ae8573b513cf189c4adeb3e12f96bf..0000000000000000000000000000000000000000 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaApplicationConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.ozgcloud.eingang.xta; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import de.ozgcloud.eingang.semantik.enginebased.xta.XtaEngineBasedAdapter; - -@Configuration -class XtaApplicationConfiguration { - - @Bean - XtaEngineBasedAdapter engineBasedAdapter() { - return new XtaEngineBasedAdapter(); - } -} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..34a807f7001122a0561f319e767c06b08904f25b --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das + * Ministerium für Energiewende, Klimaschutz, Umwelt und Natur + * Zentrales IT-Management + * + * 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.xta; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.springframework.stereotype.Component; + +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.xta.zip.ZipFileExtractor; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Component +@RequiredArgsConstructor +class XtaIncomingFilesMapper { + + private final ZipFileExtractor zipFileExtractor; + + public static final String ZIP_CONTENT_TYPE = "application/zip"; + static final Predicate<IncomingFile> IS_ZIP_FILE = contentType -> ZIP_CONTENT_TYPE.equals(contentType.getContentType()); + + public List<IncomingFile> toIncomingFiles(Collection<XtaFile> messageFiles) { + if (Objects.nonNull(messageFiles)) { + return messageFiles.stream() + .map(this::toIncomingFile) + .flatMap(this::extractZip) + .toList(); + } + return List.of(); + } + + IncomingFile toIncomingFile(XtaFile messageFile) { + if (!messageFile.contentType().equals(ZIP_CONTENT_TYPE)) { + LOG.warn("Expected XTA messageFile to be of content type " + ZIP_CONTENT_TYPE + ". Instead was " + messageFile.contentType()); + } + return IncomingFile.builder() + .name(messageFile.name()) + .contentType(messageFile.contentType()) + .file(messageFile.file()) + .size(messageFile.file().length()) + .build(); + } + + Stream<IncomingFile> extractZip(IncomingFile incomingFile) { + if (IS_ZIP_FILE.test(incomingFile)) { + try { + List<IncomingFile> extractedZips = zipFileExtractor.extractIncomingFilesSafely(incomingFile); + return extractedZips.stream(); + } catch (RuntimeException e) { + LOG.error("Cannot read source ZIP. Not extracting file", e); + return Stream.of(incomingFile); + } + } else { + return Stream.of(incomingFile); + } + } +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java index f2e05fc7684fe33d1db3dd42ae46f1f044f23ef8..af561ff948a92bee781a4745cd9b98af4ece0c8e 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java @@ -1,50 +1,51 @@ package de.ozgcloud.eingang.xta; -import java.util.Objects; +import java.util.List; +import java.util.stream.Stream; +import org.mapstruct.Context; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormHeader; import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; +import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper; +import de.ozgcloud.eingang.xdomea.XdomeaMessageData; -@Mapper +@Mapper(imports = FilesMapperHelper.class) interface XtaMessageMapper { + int VORGANG_NUMMER_SUFFIX_LENGTH = 4; @Mapping(target = "antragsteller", ignore = true) - @Mapping(target = "attachment", ignore = true) - @Mapping(target = "attachments", ignore = true) @Mapping(target = "formData", ignore = true) @Mapping(target = "id", ignore = true) - @Mapping(target = "numberOfAttachments", ignore = true) - @Mapping(target = "numberOfRepresentations", constant = "1") - @Mapping(target = "representation", ignore = true) - @Mapping(target = "representations", source = "messageFiles") @Mapping(target = "zustaendigeStelle", ignore = true) @Mapping(target = "header", source = "metaData") - FormData toFormData(XtaMessage message); + @Mapping(target = "numberOfAttachments", expression = "java(FilesMapperHelper.countAttachedFiles(xdomeaMessageData.attachments()))") + @Mapping(target = "numberOfRepresentations", dependsOn = "representations", expression = "java(getRepresentations(xdomeaMessageData).size())") + @Mapping(target = "representations", source = "xdomeaMessageData") + @Mapping(target = "representation", ignore = true) + @Mapping(target = "attachment", ignore = true) + FormData toFormData(XdomeaMessageData xdomeaMessageData, XtaMessageMetaData metaData, @Context VorgangNummerSupplier vorgangNummerSupplier); + + default List<IncomingFile> getRepresentations(XdomeaMessageData xdomeaMessageData) { + return Stream.concat( + Stream.of(xdomeaMessageData.metadataFile()), + xdomeaMessageData.representations().stream() + ).toList(); + } - @Mapping(target = "formEngineName", ignore = true) @Mapping(target = "formId", source = "messageType") @Mapping(target = "requestId", source = "messageId") + @Mapping(target = "vorgangNummer", expression = "java(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH))") @Mapping(target = "serviceKonto", ignore = true) @Mapping(target = "createdAt", source = "origin") @Mapping(target = "sender", constant = "XTA") - @Mapping(target = "formName", constant = "dFördermittelantrag") - FormHeader formHeaderFromMetaData(XtaMessageMetaData metaData); - - default IncomingFile toIncomingFile(XtaFile messageFile) { - if (Objects.nonNull(messageFile)) { - return IncomingFile.builder() - .name(messageFile.name()) - .contentType("application/zip") - .file(messageFile.file()) - .size(messageFile.file().length()) - .build(); - } - return null; - } + @Mapping(target = "formName", ignore = true) + @Mapping(target = "formEngineName", ignore = true) + FormHeader formHeaderFromMetaData(XtaMessageMetaData metaData, @Context VorgangNummerSupplier vorgangNummerSupplier); default String fromId(XtaMessageId id) { return id.toString(); diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java index 5da39aab1d30059a0e4577686a7427bc860f6278..4f59251706db33e1fe5d24ce333fb7f3a255a5a3 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java @@ -12,6 +12,9 @@ import java.util.stream.Stream; import javax.xml.namespace.QName; import javax.xml.transform.TransformerException; +import jakarta.validation.Valid; +import jakarta.xml.bind.JAXBElement; + import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -44,8 +47,6 @@ import eu.osci.ws._2008._05.transport.MsgSelector; import eu.osci.ws._2008._05.transport.MsgStatusListType; import eu.osci.ws._2008._05.transport.ObjectFactory; import eu.osci.ws._2014._10.transport.MessageMetaData; -import jakarta.validation.Valid; -import jakarta.xml.bind.JAXBElement; import lombok.NonNull; import lombok.extern.log4j.Log4j2; 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 9e60b84b7ac4ba0dafc491ae1d80742a4d002d58..2341fbf6dc93899cb0c195ee6f09be52266c5c81 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 @@ -4,13 +4,14 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; +import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper; +import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.FormHeader; -import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; import lombok.NonNull; import lombok.extern.log4j.Log4j2; @@ -18,8 +19,7 @@ import lombok.extern.log4j.Log4j2; @Log4j2 class XtaService { - static final String DFOERDERMITTELANTRAG_MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201"; - static final int VORGANG_NUMMER_SUFFIX_LENGTH = 4; + static final String XDOMEA_0201_MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201"; @Autowired private XtaRemoteService remoteService; @@ -27,9 +27,13 @@ class XtaService { private XtaMessageMapper mapper; @Autowired private VorgangNummerSupplier vorgangNummerSupplier; + @Autowired + private XdomeaMessageDataMapper xdomeaMessageDataMapper; + @Autowired + private XtaIncomingFilesMapper xtaIncomingFilesMapper; public Stream<FormData> getMessages() { - return createXtaMessageStream().filter(this::filterByMessageType).map(this::getFormData); + return createXtaMessageStream().filter(this::isSupportedMessageType).map(this::getFormData); } Stream<XtaMessageMetaData> createXtaMessageStream() { @@ -37,10 +41,8 @@ class XtaService { return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); } - // filter criteria for dFoerdermittelantrag - // https://jira.mgm-tp.com/jira/browse/OZG-3659 - boolean filterByMessageType(XtaMessageMetaData metaData) { - if (StringUtils.equals(metaData.getMessageType(), DFOERDERMITTELANTRAG_MESSAGE_TYPE)) { + boolean isSupportedMessageType(XtaMessageMetaData metaData) { + if (StringUtils.equals(metaData.getMessageType(), XDOMEA_0201_MESSAGE_TYPE)) { return true; } @@ -50,16 +52,10 @@ class XtaService { public FormData getFormData(@NonNull XtaMessageMetaData metaData) { var msg = remoteService.getMessage(metaData.getMessageId()); - var formData = mapper.toFormData(msg.toBuilder().metaData(metaData).build()); - return updateHeader(formData); - } - - FormData updateHeader(FormData formData) { - return formData.toBuilder().header(setVorgangNummer(formData.getHeader())).build(); - } + var incomingFiles = xtaIncomingFilesMapper.toIncomingFiles(msg.getMessageFiles()); + var xdomeaMessageData = xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles); - FormHeader setVorgangNummer(FormHeader formHeader) { - return formHeader.toBuilder().vorgangNummer(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH)).build(); + return mapper.toFormData(xdomeaMessageData, metaData, vorgangNummerSupplier); } public void acknowledgeReceive(@NonNull XtaMessageId messageId) { diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/LimitedInputStream.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/LimitedInputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..ee5dc7a8b70e7fe0241a60d94e98ed783f47f66e --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/LimitedInputStream.java @@ -0,0 +1,42 @@ +package de.ozgcloud.eingang.xta.zip; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class LimitedInputStream extends FilterInputStream { + static final String LIMITED_EXCEEDED_MESSAGE = "Read limit exceeded"; + + private final long maxSize; + long bytesRead; + + public LimitedInputStream(InputStream in, long maxSize) { + super(in); + this.maxSize = maxSize; + this.bytesRead = 0; + } + + @Override + public int read() throws IOException { + var byteValue = super.read(); + if (byteValue != -1) { + updateAndVerifyReadLimit(1); + } + return byteValue; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return updateAndVerifyReadLimit(super.read(b, off, len)); + } + + private int updateAndVerifyReadLimit(int newBytesRead) throws IOException { + if (newBytesRead != -1) { + bytesRead += newBytesRead; + if (bytesRead > maxSize) { + throw new IOException(LIMITED_EXCEEDED_MESSAGE); + } + } + return newBytesRead; + } +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntry.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..fec9014ca3c6ac8c743517d6b45da904b5e9b7aa --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntry.java @@ -0,0 +1,28 @@ +package de.ozgcloud.eingang.xta.zip; + +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import lombok.Builder; + +@Builder +record ReadableZipEntry(ZipEntry zipEntry, ZipFile parentZip) { + public InputStream getInputStream() throws IOException { + return parentZip.getInputStream(zipEntry); + } + + public Long getPositiveSize() { + var size = zipEntry.getSize(); + if (size < 0) { + throw new TechnicalException("Size of ZIP entry is unknown."); + } + return size; + } + + public String getName() { + return zipEntry.getName(); + } +} diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractor.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..8f162061de832319567338ed51ad2a4c5dc069d3 --- /dev/null +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractor.java @@ -0,0 +1,119 @@ +package de.ozgcloud.eingang.xta.zip; + +import java.io.File; +import java.io.IOException; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.springframework.stereotype.Component; +import org.springframework.util.MimeTypeUtils; + +import de.ozgcloud.common.binaryfile.TempFileUtils; +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; + +// TODO Resolve code duplication with ZipAttachmentReader in semantik-adapter common.zip +// Note: In contrast to the ZipAttachmentReader, here, the zip file is not included in list of extracted files +// Further, the suspicious compression ratio ZIP_MAX_THRESHOLD is evaluated on the whole zipFile, instead of individual entries +@Component +public class ZipFileExtractor { + + static final double ZIP_MAX_THRESHOLD = 100; + static final int ZIP_MAX_TOTAL_SIZE = 500 * 1024 * 1024; + static final int ZIP_MAX_ENTRIES = 100; + + public List<IncomingFile> extractIncomingFilesSafely(IncomingFile zipIncomingFile) { + var zipFile = zipIncomingFile.getFile(); + verifyLimits(zipFile); + return extractIncomingFiles(zipFile); + } + + void verifyLimits(File zipFile) { + var uncompressedSize = sumUncompressedEntrySizes(zipFile); + verifySizeLimit(uncompressedSize); + verifyCompressionRatio(zipFile, uncompressedSize); + } + + private void verifySizeLimit(long uncompressedSize) { + if (uncompressedSize > getZipMaxTotalSize()) { + throw new TechnicalException("Expect uncompressed size %s to be smaller than %d!".formatted(uncompressedSize, getZipMaxTotalSize())); + } + } + + private void verifyCompressionRatio(File zipFile, long totalSize) { + var compressionRatio = (double) totalSize / zipFile.length(); + if (compressionRatio > ZIP_MAX_THRESHOLD) { + throw new TechnicalException( + "Expect compression ratio %s to be smaller than %s! A zip bomb attack is suspected!".formatted(compressionRatio, + ZIP_MAX_THRESHOLD)); + } + } + + int getZipMaxTotalSize() { + return ZIP_MAX_TOTAL_SIZE; + } + + Long sumUncompressedEntrySizes(File zipFile) { + return mapZipEntries(zipFile, ReadableZipEntry::getPositiveSize) + .stream() + .mapToLong(Long::longValue) + .sum(); + } + + List<IncomingFile> extractIncomingFiles(File zipFile) { + return mapZipEntries(zipFile, this::mapReadableEntryToIncomingFile); + } + + private IncomingFile mapReadableEntryToIncomingFile(ReadableZipEntry entry) { + File file; + try (var inputStream = new LimitedInputStream(entry.getInputStream(), entry.getPositiveSize())) { + file = TempFileUtils.writeTmpFile(inputStream); + } catch (IOException | de.ozgcloud.common.errorhandling.TechnicalException e) { + throw new TechnicalException("Failed reading zip file element %s!".formatted(entry.getName()), e); + } + return createIncomingFile(file, entry.zipEntry()); + } + + <T> List<T> mapZipEntries(File zipFile, Function<ReadableZipEntry, T> mappingFunction) { + try (ZipFile zip = new ZipFile(zipFile)) { + var index = new AtomicInteger(); + var mappedElements = new ArrayList<T>(); + zip.stream().forEach(element -> { + if (index.getAndIncrement() >= ZIP_MAX_ENTRIES) { + throw new TechnicalException("Expect zip files to have at most %d entries!".formatted(ZIP_MAX_ENTRIES)); + } + mappedElements.add( + mappingFunction.apply( + ReadableZipEntry.builder() + .parentZip(zip) + .zipEntry(element) + .build() + ) + ); + }); + return mappedElements; + } catch (IOException e) { + throw new TechnicalException("Failed reading zip file!", e); + } + } + + IncomingFile createIncomingFile(File file, ZipEntry zipEntry) { + return IncomingFile.builder() + .name(zipEntry.getName()) + .size(zipEntry.getSize()) + .contentType(getContentType(zipEntry.getName())) + .file(file) + .build(); + } + + String getContentType(String name) { + Objects.requireNonNull(name); + return Objects.requireNonNullElse(URLConnection.guessContentTypeFromName(name), MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE); + } +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94f24a83b05a8f49b26ad434438311cb8368f9fe --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapperTest.java @@ -0,0 +1,179 @@ +package de.ozgcloud.eingang.xdomea; + +import static de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.stream.Stream; + +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; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; + +class XdomeaMessageDataMapperTest { + + @Spy + @InjectMocks + private XdomeaMessageDataMapper fileClassifier; + + @Mock + private XdomeaXMLValueReader valueReader; + + @DisplayName("find Xdomea XML file") + @Nested + class TestFindXdomeaXmlFile { + + private static final String FILE_NAME_WITHOUT_SUFFIX = "some-file-name.xml"; + private static final String FILE_NAME_WITH_SUFFIX = "some-file-name" + XDOMEA_0201_XML_FILE_NAME_SUFFIX; + + @DisplayName("should throw if not found") + @Test + void shouldThrowIfNotFound() { + var incomingFilesWithout = List.of(IncomingFileTestFactory.createBuilder().name(FILE_NAME_WITHOUT_SUFFIX).build()); + + assertThatThrownBy(() -> fileClassifier.findXdomeaXMLFile(incomingFilesWithout)) + .isInstanceOf(TechnicalException.class); + } + + @DisplayName("should return if found") + @Test + void shouldReturnIfFound() { + var targetIncomingFile = IncomingFileTestFactory.createBuilder().name(FILE_NAME_WITH_SUFFIX).build(); + var incomingFilesWith = List.of( + IncomingFileTestFactory.createBuilder().name(FILE_NAME_WITHOUT_SUFFIX).build(), + targetIncomingFile + ); + + var primaryRepresentation = fileClassifier.findXdomeaXMLFile(incomingFilesWith); + + assertThat(primaryRepresentation).isEqualTo(targetIncomingFile); + } + } + + @DisplayName("find primary representation name") + @Nested + class TestFindPrimaryRepresentationName { + private static final String FILE_NAME_WITHOUT_XML_SUFFIX = "some-file-name.pdf"; + private static final String FILE_NAME_WITHOUT_XML_SUFFIX2 = "some-file-name.xml.pdf"; + private static final String FILE_NAME_WITH_XML_SUFFIX = "some-file-name.xml"; + private static final String FILE_NAME_WITH_XML_SUFFIX2 = "some-file-name.pdf.xml"; + + @DisplayName("should throw if no xml suffix") + @Test + void shouldThrowIfNoXmlSuffix() { + var listWithoutSuffix = List.of(FILE_NAME_WITHOUT_XML_SUFFIX, FILE_NAME_WITHOUT_XML_SUFFIX2); + + assertThrows(TechnicalException.class, () -> fileClassifier.findPrimaryRepresentationName(listWithoutSuffix)); + } + + @DisplayName("should return first with xml suffix") + @Test + void shouldReturnFirstWithXmlSuffix() { + var listWithSuffix = List.of(FILE_NAME_WITHOUT_XML_SUFFIX, FILE_NAME_WITH_XML_SUFFIX, FILE_NAME_WITHOUT_XML_SUFFIX2, + FILE_NAME_WITH_XML_SUFFIX2); + + var fileName = fileClassifier.findPrimaryRepresentationName(listWithSuffix); + + assertThat(fileName).isEqualTo(FILE_NAME_WITH_XML_SUFFIX); + } + } + + @DisplayName("classify attachments and representations") + @Nested + class TestClassifyAttachmentsAndRepresentations { + + private static final String XDOMEA_XML_NAME = "xdomea.xml"; + private static final String REPR_XML_NAME = "repr.xml"; + private static final String REPR_PDF_NAME = "repr.pdf"; + private static final String ATTATCHMENT_XML_NAME = "att.xml"; + private static final String ATTATCHMENT_PNG_NAME = "att.png"; + private static final String ATTATCHMENT_PDF_NAME = "att.pdf"; + + @Mock + private IncomingFile xdomeaXMLFile; + + private List<IncomingFile> incomingFileList; + + @BeforeEach + void mock() { + incomingFileList = Stream.of( + XDOMEA_XML_NAME, + REPR_XML_NAME, + REPR_PDF_NAME, + ATTATCHMENT_XML_NAME, + ATTATCHMENT_PNG_NAME, + ATTATCHMENT_PDF_NAME + ) + .map(name -> IncomingFileTestFactory.createBuilder().name(name).build()) + .toList(); + doReturn(xdomeaXMLFile).when(fileClassifier).findXdomeaXMLFile(incomingFileList); + + when(xdomeaXMLFile.getName()).thenReturn(XDOMEA_XML_NAME); + + var representationFileNames = List.of(REPR_PDF_NAME, REPR_XML_NAME); + when(valueReader.readRepresentationFileNames(xdomeaXMLFile)).thenReturn(representationFileNames); + doReturn(REPR_XML_NAME).when(fileClassifier).findPrimaryRepresentationName(representationFileNames); + } + + @DisplayName("should contain xdomea metadata file") + @Test + void shouldContainXdomeaMetadataFile() { + var classification = doClassify(); + + var primaryDocument = classification.metadataFile(); + + assertThat(primaryDocument.getName()).isEqualTo(XDOMEA_XML_NAME); + } + + @DisplayName("should contain representations") + @Test + void shouldContainRepresentations() { + var classification = doClassify(); + + var resultRepresentationFileNames = classification.representations().stream() + .map(IncomingFile::getName) + .toList(); + // Expect that the primary representation xml file is moved to the first position + assertThat(resultRepresentationFileNames).isEqualTo(List.of(REPR_XML_NAME, REPR_PDF_NAME)); + } + + @DisplayName("should contain attachments") + @Test + void shouldContainAttachments() { + var classification = doClassify(); + + var resultAttachmentFileNames = classification.attachments() + .getFirst() + .getFiles().stream() + .map(IncomingFile::getName) + .toList(); + assertThat(resultAttachmentFileNames).isEqualTo(List.of(ATTATCHMENT_XML_NAME, ATTATCHMENT_PNG_NAME, ATTATCHMENT_PDF_NAME)); + } + + @DisplayName("should have attachment group name") + @Test + void shouldHaveAttachmentGroupName() { + var classification = doClassify(); + + var resultAttachmentGroupName = classification.attachments() + .getFirst() + .getName(); + assertThat(resultAttachmentGroupName).isEqualTo(ATTACHMENT_GROUP_NAME); + } + + private XdomeaMessageData doClassify() { + return fileClassifier.mapIncomingFilesToXdomeaMessageData(incomingFileList); + } + } + +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..90a659b8ddddb9cbef12e8c54da9f33ee213ab74 --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataTestFactory.java @@ -0,0 +1,19 @@ +package de.ozgcloud.eingang.xdomea; + +import java.util.List; + +import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; + +public class XdomeaMessageDataTestFactory { + public static XdomeaMessageData create() { + return createBuilder().build(); + } + + public static XdomeaMessageData.XdomeaMessageDataBuilder createBuilder() { + return XdomeaMessageData.builder() + .metadataFile(IncomingFileTestFactory.createBuilder().name("xdomea-primary-document.xml").build()) + .representations(List.of(IncomingFileTestFactory.create())) + .attachment(IncomingFileGroup.builder().file(IncomingFileTestFactory.create()).build()); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..fdc793156871725f8e9ce415f05b652ae0dcc435 --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java @@ -0,0 +1,58 @@ +package de.ozgcloud.eingang.xdomea; + +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; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.common.test.TestUtils; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import lombok.SneakyThrows; + +class XdomeaXMLValueReaderTest { + private static final String XML_FILE_NAME = "file.xml"; + private static final String PDF_FILE_NAME = "file.pdf"; + + @Spy + @InjectMocks + private XdomeaXMLValueReader valueReader; + + @DisplayName("read representation file names") + @Nested + class TestReadRepresentationFileNames { + + @Mock + IncomingFile incomingXmlFile; + + @DisplayName("should find 'Dateiname' elements in MSR mantelantrag") + @ParameterizedTest + @ValueSource(strings = { + "xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml", + "xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml" + }) + @SneakyThrows + void shouldFindDateinameElements(String antragXMLFilename) { + var xmlString = TestUtils.loadTextFile( + antragXMLFilename, + XML_FILE_NAME + "\n", + PDF_FILE_NAME); + 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)); + } + + } + +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java index db83159ccffc9185959569982fc9d09c7479a6fe..acd02b8efce3f09542c8dc5c748850027ad27072 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java @@ -1,11 +1,12 @@ package de.ozgcloud.eingang.xta; import de.ozgcloud.eingang.common.formdata.FormHeader; -import de.ozgcloud.eingang.common.formdata.FormHeader.FormHeaderBuilder;; +import de.ozgcloud.eingang.common.formdata.FormHeader.FormHeaderBuilder; public class FormHeaderTestFactory { - private static final String FORM_NAME = "dFördermittelantrag"; + private static final String FORM_NAME = "xdomea"; + static final String VORGANGNUMMER = "vorgangNummer"; static FormHeader create() { return createBuilder().build(); @@ -15,6 +16,7 @@ public class FormHeaderTestFactory { return FormHeader.builder() .sender("XTA") .requestId(XtaMessageTestFactory.MESSAGE_ID.toString()) + .vorgangNummer(VORGANGNUMMER) .formName(FORM_NAME) .formId(XtaMessageMetaDataTestFactory.MESSAGE_TYPE) .createdAt(XtaMessageMetaDataTestFactory.ORIGIN); diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java index 59bddcf63df7c9135a753a6ee4aab49a375bd087..8e2d830f342905d66d07dca69cd304b92bef142c 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java @@ -1,32 +1,21 @@ package de.ozgcloud.eingang.xta; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import de.ozgcloud.eingang.Application; -import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; -import de.ozgcloud.eingang.semantik.enginebased.xta.XtaEngineBasedAdapter; @ActiveProfiles({ "local", "itcase" }) @SpringBootTest(classes = Application.class) class XtaApplicationTest { - @Autowired - private EngineBasedSemantikAdapter engineBasedAdapter; - @Test void startup() { // should start without exception; assertTrue(true); } - @Test - void shouldHaveEngineBasedAdapter() { - assertThat(engineBasedAdapter).isInstanceOf(XtaEngineBasedAdapter.class); - } } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java index f6eaca430bafa55daa30defef2ca846a3f91a07a..5512656128e6245be33f1f274e87f536637914ca 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java @@ -13,18 +13,22 @@ class XtaFileTestFactory { static final String NAME = "Test_File"; static final String CONTENT = "slkafj3jifsdasx"; + static final String ZIP_CONTENT_TYPE = "application/zip"; static XtaFile create() { return createBuilder().build(); } static XtaFile.XtaFileBuilder createBuilder() { - return XtaFile.builder().name(NAME).file(createFile()); + return XtaFile.builder() + .name(NAME) + .contentType(ZIP_CONTENT_TYPE) + .file(createFile()); } @SneakyThrows private static File createFile() { - File tFile = File.createTempFile("test", "txt"); + File tFile = File.createTempFile("test", "zip"); tFile.deleteOnExit(); FileUtils.write(tFile, CONTENT, StandardCharsets.UTF_8); 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 beb10f64917e4923553562d5ffa19298e4a58db8..6a5705a31bc4ea95c96227e291f3d4b3e814da45 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 @@ -1,12 +1,20 @@ package de.ozgcloud.eingang.xta; import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.InstanceOfAssertFactories.*; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; +import java.util.Optional; + import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.springframework.beans.factory.annotation.Autowired; @@ -15,104 +23,231 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Bean; import org.springframework.test.context.ActiveProfiles; -import de.ozgcloud.common.test.TestUtils; import de.ozgcloud.eingang.Application; import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.ServiceKonto; -import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress; -import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier; import de.ozgcloud.eingang.router.VorgangRemoteService; +import de.ozgcloud.vorgang.vorgang.GrpcEingang; -@SpringBootTest(classes = { Application.class, ActivateXTARunnerConfig.class }) -@ActiveProfiles({ "local", "itcase" }) +@SpringBootTest(classes = { + Application.class, + XtaITCase.ActivateXTARunnerConfig.class +}) +@ActiveProfiles({ "itcase" }) class XtaITCase { - @MockBean - private XtaRemoteService remoteService; @MockBean private VorgangRemoteService vorgangRemoteService; - @Autowired - private XtaRunner runner; + @MockBean + private XtaRemoteService xtaRemoteService; + @Captor - private ArgumentCaptor<FormData> formDataCaptor; + private ArgumentCaptor<FormData> formDataArgumentCaptor; - @BeforeEach - void prepareXtaRemoteService() { - when(remoteService.getMessagesMetadata()).thenReturn(XtaMessageMetaDatasAndHeaderTestFactory.create()); + @Captor + private ArgumentCaptor<GrpcEingang> eingangArgumentCaptor; - when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn( - XtaMessageTestFactory.createBuilder() - .clearMessageFiles() - .messageFile(XtaFileTestFactory.withFileContent(TestUtils.loadFile("test_content.zip"), "test_content.zip")) - .build()); - } + @Captor + private ArgumentCaptor<Optional<String>> organisationseinheitenIdArgumentCaptor; - @Test - void shouldGetMessage() { - runner.onApplicationEvent(null); + @Autowired + private XtaRunner runner; - verify(remoteService).getMessage(XtaMessageTestFactory.MESSAGE_ID); + @DisplayName("run get xta messages") + @Nested + class TestRunGetXtaMessages { + @BeforeEach + void setup() { + when(vorgangRemoteService.createVorgang(any(), any(), any())).thenReturn("vorgangId(unused)"); + } + + @DisplayName("should have three representations with pdf") + @TestZipFileNamesWithPdf + void shouldHaveThreeRepresentationsWithPdf(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var eingang = captureEingang(); + assertThat(eingang.getNumberOfRepresentations()).isEqualTo(3); + } + + @DisplayName("should send two representations without pdf") + @TestZipFileNamesWithoutPdf + void shouldSendTwoXMLRepresentationsWithoutPdf(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var eingang = captureEingang(); + assertThat(eingang.getNumberOfRepresentations()).isEqualTo(2); + } + + @DisplayName("should have no attachments") + @TestZipFileNamesWithoutAnlage + void shouldHaveNoAttachments(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var eingang = captureEingang(); + assertThat(eingang.getNumberOfAttachments()).isZero(); + } + + @DisplayName("should have one attachment") + @TestZipFileNamesWithAnlage + void shouldHaveOneAttachment(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var eingang = captureEingang(); + assertThat(eingang.getNumberOfAttachments()).isEqualTo(1); + } + + @DisplayName("should have postfach id") + @TestZipFileNamesWithServiceKonto + void shouldHavePostfachId(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var serviceKonto = captureEingang() + .getHeader() + .getServiceKonto(); + assertThat(serviceKonto).isNotNull(); + var postfachId = serviceKonto + .getPostfachAddresses(0) + .getIdentifier() + .getProperty(0) + .getValue(0); + assertThat(postfachId).isEqualTo("4dd01647-b9d9-4775-1b50-08da3d83800a"); + } + + @DisplayName("should have organistationseinheit ID") + @TestZipFileNames + void shouldHaveOrganistationseinheitId(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var organisationseinheitenId = captureEingang() + .getZustaendigeStelle() + .getOrganisationseinheitenId(); + assertThat(organisationseinheitenId).isEqualTo("9795669"); + } + + @DisplayName("should have vorgang nummer") + @TestZipFileNames + void shouldHaveVorgangNummer(String zipFileName) { + mockNachrichtenBroker(zipFileName); + + runner.runGetXtaMessages(); + + var vorgangNummer = captureEingang().getHeader().getVorgangNummer(); + assertThat(vorgangNummer).hasSize(9); + } + + private GrpcEingang captureEingang() { + verify(vorgangRemoteService, times(1)) + .createVorgang( + formDataArgumentCaptor.capture(), + eingangArgumentCaptor.capture(), + organisationseinheitenIdArgumentCaptor.capture() + ); + + assertThat(formDataArgumentCaptor.getValue()).isNotNull(); + assertThat(eingangArgumentCaptor.getValue()).isNotNull(); + assertThat(organisationseinheitenIdArgumentCaptor.getValue()).isPresent(); + + return eingangArgumentCaptor.getValue(); + } } - @Test - void shouldCloseMessage() { - runner.onApplicationEvent(null); - - verify(remoteService, timeout(2000)).close(XtaMessageTestFactory.MESSAGE_ID); + private void mockNachrichtenBroker(String zipFileName) { + when(xtaRemoteService.getMessage(any(XtaMessageId.class))).thenReturn( + XtaResponseTestFactory.createGetMessageResponse(zipFileName) + ); + when(xtaRemoteService.getMessagesMetadata()) + .thenReturn(XtaResponseTestFactory.createGetStatusListResponse(List.of(zipFileName))); + when(xtaRemoteService.getNextMessagesMetadata(any())) + .thenReturn(XtaResponseTestFactory.createEmptyGetStatusListResponse()); } - @Test - void shouldSend4Representations() { - runner.onApplicationEvent(null); - - verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), any(), any()); - assertThat(formDataCaptor.getValue().getNumberOfRepresentations()).isEqualTo(4); - assertThat(formDataCaptor.getValue().getRepresentations()).hasSize(4); + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "dfoerdermittel_without_anlage.zip", + "brauchtumsfeuer_without_anlage.zip", + "mantelantrag_without_anlage.zip" + }) + @interface TestZipFileNamesWithoutAnlage { } - @Test - void shouldHavePostfachId() { - runner.onApplicationEvent(null); - - var formData = captorFormData(); - - assertThat(formData.getHeader().getServiceKonto()).describedAs("ServiceKonto").isNotNull() - .extracting(ServiceKonto::getPostfachAddresses).asList().hasSize(1).first() - .asInstanceOf(type(PostfachAddress.class)) - .extracting(PostfachAddress::getIdentifier).isInstanceOf(StringBasedIdentifier.class).asInstanceOf(type(StringBasedIdentifier.class)) - .extracting(StringBasedIdentifier::getPostfachId).isEqualTo("4dd01647-b9d9-4775-1b50-08da3d83800a"); + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "dfoerdermittel_with_anlage.zip", + "brauchtumsfeuer_with_anlage.zip", + "mantelantrag_with_anlage.zip" + }) + @interface TestZipFileNamesWithAnlage { } - @Test - void shouldHaveOrganisationsEinheitId() { - runner.onApplicationEvent(null); - - var formData = captorFormData(); - - assertThat(formData.getZustaendigeStelle().getOrganisationseinheitenId()).isEqualTo("9795669"); + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "dfoerdermittel_without_anlage.zip", + "mantelantrag_without_anlage.zip", + "brauchtumsfeuer_without_anlage.zip", + "dfoerdermittel_with_anlage.zip", + "mantelantrag_with_anlage.zip", + "brauchtumsfeuer_with_anlage.zip", + }) + @interface TestZipFileNamesWithPdf { } - @Test - void shouldHaveVorgangNummer() { - runner.onApplicationEvent(null); - - var formData = captorFormData(); - - assertThat(formData.getHeader().getVorgangNummer()).hasSize(9); + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "waffenschein.zip" + }) + @interface TestZipFileNamesWithoutPdf { } - private FormData captorFormData() { - verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), any(), any()); - - return formDataCaptor.getValue(); + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "dfoerdermittel_without_anlage.zip", + "dfoerdermittel_with_anlage.zip", + }) + @interface TestZipFileNamesWithServiceKonto { } -} + @Target({ ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest + @ValueSource(strings = { + "dfoerdermittel_without_anlage.zip", + "mantelantrag_without_anlage.zip", + "brauchtumsfeuer_without_anlage.zip", + "dfoerdermittel_with_anlage.zip", + "mantelantrag_with_anlage.zip", + "brauchtumsfeuer_with_anlage.zip", + "waffenschein.zip" + }) + @interface TestZipFileNames { + } -class ActivateXTARunnerConfig { - @Bean - XtaRunner xtaRunner() { - return new XtaRunner(); + static class ActivateXTARunnerConfig { + @Bean + XtaRunner xtaRunner() { + return new XtaRunner(); + } } -} \ No newline at end of file +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0dfa769d688d5bab27fce58f4673282a7e86caac --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das + * Ministerium für Energiewende, Klimaschutz, Umwelt und Natur + * Zentrales IT-Management + * + * 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.xta; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.xta.zip.ZipFileExtractor; + +class XtaIncomingFilesMapperTest { + @Spy + @InjectMocks + private XtaIncomingFilesMapper mapper; + + @Mock + private ZipFileExtractor extractor; + + private static final String ZIP_CONTENT_TYPE = "application/zip"; + + @Nested + class TestToIncomingFiles { + + @Test + void shouldMapToIncomingFiles() { + var xtaFile = XtaFileTestFactory.create(); + var incomingFile = IncomingFileTestFactory.create(); + when(mapper.toIncomingFile(xtaFile)).thenReturn(incomingFile); + when(mapper.extractZip(incomingFile)).thenAnswer((x) -> Stream.of(incomingFile)); + + mapper.toIncomingFiles(List.of(xtaFile, xtaFile)); + + inOrder(mapper).verify(mapper, calls(2)).toIncomingFile(xtaFile); + inOrder(mapper).verify(mapper, calls(2)).extractZip(incomingFile); + } + + @Test + void shouldHandleMissingMessageFile() { + var fileGroup = mapper.toIncomingFiles(null); + + assertThat(fileGroup).isEmpty(); + } + } + + @Nested + class ToIncomingFile { + @Test + void shouldHaveMessageFile() { + var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); + + assertThat(inFile.getContentStream()).isNotNull(); + } + + @Test + void shouldHaveFileName() { + var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); + + assertThat(inFile.getName()).isEqualTo(XtaFileTestFactory.NAME); + } + + @Test + void shouldHaveZipContentType() { + var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); + + assertThat(inFile.getContentType()).isEqualTo(XtaFileTestFactory.ZIP_CONTENT_TYPE); + } + + @Test + void shouldHaveSize() { + var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); + + assertThat(inFile.getSize()).isEqualTo(XtaFileTestFactory.CONTENT.length()); + } + } + + @Nested + class TestExtractZip { + + @Mock + IncomingFile outFile1; + + @Mock + IncomingFile outFile2; + + + @Test + void shouldExtractZipFiles() { + var expectedExtractedFiles = List.of(outFile1, outFile2); + var zipFile = createTestIncomingFile(); + when(extractor.extractIncomingFilesSafely(zipFile)).thenReturn(expectedExtractedFiles); + + var extractedFiles = mapper.extractZip(zipFile).toList(); + + assertThat(extractedFiles).isEqualTo(expectedExtractedFiles); + } + + IncomingFile createTestIncomingFile() { + return IncomingFileTestFactory.createBuilder() + .name("attachments.zip") + .contentType(ZIP_CONTENT_TYPE) + .build(); + } + + @Test + void shouldIgnoreNonZipFiles() { + var incomingFile = IncomingFileTestFactory.create(); + + var extractedFiles = mapper.extractZip(incomingFile).toList(); + + assertThat(extractedFiles).containsExactly(incomingFile); + } + } + + @Test + void testIsZipFilePredicate() { + assertThat(XtaIncomingFilesMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.create())).isFalse(); + assertThat(XtaIncomingFilesMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.createBuilder().contentType(ZIP_CONTENT_TYPE).build())) + .isTrue(); + } +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java index 7655eb0d5a3253758a940dba565a2bedb3c6c8fe..b9bcda822a302872474e1c4341cbe08b11675b99 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java @@ -1,95 +1,81 @@ package de.ozgcloud.eingang.xta; +import static de.ozgcloud.eingang.xta.XtaMessageMapper.*; 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 org.mockito.Spy; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; +import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory; +import de.ozgcloud.eingang.xdomea.XdomeaMessageData; + class XtaMessageMapperTest { @Spy @InjectMocks private XtaMessageMapper mapper = Mappers.getMapper(XtaMessageMapper.class); + @Mock + private VorgangNummerSupplier vorgangNummerSupplier; + @Nested class TestToFormData { - @Test - void shouldMapAllToForm() { - var formData = mapper.toFormData(XtaMessageTestFactory.create()); + private XtaMessageMetaData xtaMessageMetaData; + private XdomeaMessageData xdomeaMessageData; - assertThat(formData).usingRecursiveComparison().ignoringFields("id", "representations") - .isEqualTo(FormDataTestFactory.create()); + @BeforeEach + void mock() { + xtaMessageMetaData = XtaMessageMetaDataTestFactory.create(); + xdomeaMessageData = XdomeaMessageDataTestFactory.create(); + when(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH)).thenReturn(FormHeaderTestFactory.VORGANGNUMMER); } @Test - void shouldHaveMessageFileAsRepresentation() { - var formData = mapper.toFormData(XtaMessageTestFactory.create()); + void shouldMapRepresentations() { + var formData = doMapping(); - assertThat(formData.getRepresentations()).hasSize(1); + assertThat(formData.getRepresentations()).containsExactly(xdomeaMessageData.metadataFile(), xdomeaMessageData.representations().getFirst()); } @Test - void shouldCallToIncomingFile() { - XtaMessage message = XtaMessageTestFactory.create(); - - mapper.toFormData(message); + void shouldSetNumberOfAttachments() { + var formData = doMapping(); - verify(mapper).toIncomingFile(notNull()); + assertThat(formData.getNumberOfAttachments()).isEqualTo(1); } - @Nested - class ToFormHeader { - @Test - void shouldMapToFormHeader() { - var mapped = mapper.formHeaderFromMetaData(XtaMessageMetaDataTestFactory.create()); + @Test + void shouldSetNumberOfRepresentations() { + var formData = doMapping(); - assertThat(mapped).usingRecursiveComparison().isEqualTo(FormHeaderTestFactory.create()); - } + assertThat(formData.getNumberOfRepresentations()).isEqualTo(2); } - @Nested - class ToIncomingFile { - @Test - void shouldHaveMessageFile() { - var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); - - assertThat(inFile.getContentStream()).isNotNull(); - } - - @Test - void shouldHaveFileName() { - var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); - - assertThat(inFile.getName()).isEqualTo(XtaFileTestFactory.NAME); - } - - @Test - void shouldHaveZipContentType() { - var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); - - assertThat(inFile.getContentType()).isEqualTo("application/zip"); - } - - @Test - void shouldHaveSize() { - var inFile = mapper.toIncomingFile(XtaFileTestFactory.create()); + @Test + void shouldMapAttachments() { + var formData = doMapping(); - assertThat(inFile.getSize()).isEqualTo(XtaFileTestFactory.CONTENT.length()); - } + assertThat(formData.getAttachments()).isEqualTo(xdomeaMessageData.attachments()); + } - @Test - void shouldHandleMissingMessageFile() { - var fileGroup = mapper.toIncomingFile(null); + @Test + void shouldMapVorgangNummer() { + var formData = doMapping(); - assertThat(fileGroup).isNull(); - } + assertThat(formData.getHeader().getVorgangNummer()).isEqualTo(FormHeaderTestFactory.VORGANGNUMMER); } + private FormData doMapping() { + return mapper.toFormData(xdomeaMessageData, xtaMessageMetaData, vorgangNummerSupplier); + } } } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java index cb5c3f846497e9e8d9c2e39dc1fb58e4f14144da..59d354ecb7c21690e7656712e51c7c5bc56428a3 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java @@ -3,11 +3,13 @@ package de.ozgcloud.eingang.xta; import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; import org.mockito.Spy; class XtaRemoteServiceConfigurationTest { @Spy + @InjectMocks XtaRemoteServiceConfiguration configuration; @Test diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java index 381cce5eaf3711843971ff76eaf1f9454ee0baf2..cc85f76f2d5cff5cf9556a7613493647f05f740b 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java @@ -54,7 +54,7 @@ class XtaRemoteServiceITCase { class TestGetMessage { @Test void shouldSendRequest() { - var result = remoteService.getMessage("urn:de:xta:messageid:dataport_xta_210:81e40808-91c6-4765-aaf4-1aa62fec8be9"); + var result = remoteService.getMessage("urn:de:xta:messageid:dataport_xta_210:20eb297a-e224-45a0-9376-5ebd4d9bcc9a"); assertThat(result).isNotNull(); } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java index dd6b6d41529a9446a78b76bdf8ccd2bf404a3cb0..a1c37d0b970039056a996ab875c6476a60abd4c5 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java @@ -114,7 +114,7 @@ class XtaRemoteServiceTest { } @Test - void hosuldReturnMessageWithFile() { + void shouldReturnMessageWithFile() { var message = service.getMessage(XtaMessageTestFactory.MESSAGE_ID); assertThat(message.getMessageFiles()).hasSize(1).contains(file); diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaResponseTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaResponseTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..4e6fed5d2772f9799261cc5b368619c987810c6a --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaResponseTestFactory.java @@ -0,0 +1,140 @@ +package de.ozgcloud.eingang.xta; + +import static de.ozgcloud.eingang.xta.zip.TestZipFileFactory.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.codec.Resources; +import org.apache.commons.io.IOUtils; + +import de.ozgcloud.common.binaryfile.TempFileUtils; + +public class XtaResponseTestFactory { + + public static final Map<String, String> MESSAGE_TYPE_BY_ATTACHMENT_FILENAME = Map.of( + "mantelantrag_without_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201", + "dfoerdermittel_without_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201", + "brauchtumsfeuer_without_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201", + "versammlungsanzeige.xml", "fim.S17000652.17000652001004", + "mantelantrag_with_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201", + "dfoerdermittel_with_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201", + "brauchtumsfeuer_with_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201", + "waffenschein.zip", "Geschaeftsgang.Geschaeftsgang.0201" + ); + + private static final Map<String, String> MESSAGE_ID_BY_ATTACHMENT_FILENAME = MESSAGE_TYPE_BY_ATTACHMENT_FILENAME + .keySet().stream() + .collect(Collectors.toMap(name -> name, name -> generateMessageID())); + + private static String generateMessageID() { + return "urn:de:xta:messageid:dataport_xta_210:%s".formatted(UUID.randomUUID().toString()); + } + + public static XtaMessageMetaDatasAndHeader createEmptyGetStatusListResponse() { + return XtaMessageMetaDatasAndHeader.builder() + .msgBoxRequestID("testid-empty") + .moreMessagesAvailable(false) + .messages(Stream.empty()) + .build(); + } + + public static XtaMessageMetaDatasAndHeader createGetStatusListResponse(List<String> xtaAttachmentFileNames) { + var messageMetaDataItems = xtaAttachmentFileNames.stream() + .map(name -> + XtaMessageMetaData.builder() + .messageId(new XtaMessageId(MESSAGE_ID_BY_ATTACHMENT_FILENAME.get(name))) + .messageType(MESSAGE_TYPE_BY_ATTACHMENT_FILENAME.get(name)) + .origin(ZonedDateTime.now()) + .delivery(ZonedDateTime.now()) + .build() + ) + .toList(); + + return XtaMessageMetaDatasAndHeader.builder() + .msgBoxRequestID("testid-withattachment") + .moreMessagesAvailable(true) + .messages(messageMetaDataItems.stream()) + .build(); + } + + public static XtaMessage createGetMessageResponse(String xtaAttachmentFileName) { + File file; + try (var inputStream = getAttachmentInputStream(xtaAttachmentFileName)) { + file = TempFileUtils.writeTmpFile(inputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return XtaMessage.builder() + .messageFile(XtaFile.builder() + .contentType("application/zip") + .name(xtaAttachmentFileName) + .size(BigInteger.valueOf(file.length())) + .file(file) + .build()) + .build(); + } + + private static InputStream getAttachmentInputStream(String xtaAttachmentFileName) { + var attachmentResourcePath = getAttachmentFilePath(xtaAttachmentFileName); + if (xtaAttachmentFileName.endsWith(".zip")) { + try { + return new FileInputStream( + createAttachmentZipFile( + attachmentResourcePath.replace(".zip", ""))); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } else { + return Resources.getInputStream(attachmentResourcePath); + } + } + + private static File createAttachmentZipFile(String attachmentResourceDirectory) { + return createTempZipFile(listResourceFileNames(attachmentResourceDirectory) + .map(subName -> { + try { + return TestZipEntry.builder() + .name(subName) + .content(IOUtils.toByteArray(Resources.getInputStream(attachmentResourceDirectory + "/" + subName))) + .build(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + ).toList()); + } + + private static Stream<String> listResourceFileNames(String resourceDirectoryPath) { + try (var inputStream = Resources.getInputStream(resourceDirectoryPath)) { + return Arrays.stream(IOUtils.toString(inputStream, StandardCharsets.UTF_8).split("\n")); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static String getMessageType(String xtaAttachmentFileName) { + return Objects.requireNonNull( + MESSAGE_TYPE_BY_ATTACHMENT_FILENAME.get(xtaAttachmentFileName), + "Xta-message type for '%s' has to be configured!".formatted(xtaAttachmentFileName) + ); + } + + private static String getAttachmentFilePath(String xtaAttachmentFileName) { + return "mock-responses/getMessage/%s/%s".formatted(getMessageType(xtaAttachmentFileName), xtaAttachmentFileName); + } +} 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 d1fc3de86803ba5fc9c49a574011b41adf8e3be0..75a00a6610db89ffeaed0ba620d4676038fda296 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 @@ -4,9 +4,9 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.List; import java.util.stream.Stream; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -16,8 +16,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; +import de.ozgcloud.eingang.xdomea.XdomeaMessageData; +import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory; +import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper; class XtaServiceTest { @@ -34,12 +37,17 @@ class XtaServiceTest { @Mock private VorgangNummerSupplier vorgangNummerSupplier; + @Mock + private XtaIncomingFilesMapper incomingFilesMapper; + + @Mock + private XdomeaMessageDataMapper xdomeaMessageDataMapper; + @Nested class TestGetMessagesAsFormData { - private XtaMessageMetaDatasAndHeader metaData = XtaMessageMetaDatasAndHeaderTestFactory.create(); - private XtaMessageMetaData messageMetaData = XtaMessageMetaDataTestFactory.create(); - private XtaMessage message = XtaMessageTestFactory.create(); + private final XtaMessageMetaData messageMetaData = XtaMessageMetaDataTestFactory.create(); + private final XtaMessage message = XtaMessageTestFactory.create(); @BeforeEach void setup() { @@ -55,19 +63,17 @@ class XtaServiceTest { @Test void shouldCallFilterByMessageType() { - when(mapper.toFormData(any())).thenReturn(FormDataTestFactory.create()); - when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message); + setupMocks(); service.getMessages().toList(); - verify(service).filterByMessageType(messageMetaData); + verify(service).isSupportedMessageType(messageMetaData); } @Test void shouldCallGetFormData() { - when(mapper.toFormData(any())).thenReturn(FormDataTestFactory.create()); - when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message); - doReturn(true).when(service).filterByMessageType(messageMetaData); + setupMocks(); + doReturn(true).when(service).isSupportedMessageType(messageMetaData); service.getMessages().toList(); @@ -76,51 +82,64 @@ class XtaServiceTest { @Test void shouldNotCallGetFormData() { - doReturn(false).when(service).filterByMessageType(messageMetaData); + doReturn(false).when(service).isSupportedMessageType(messageMetaData); service.getMessages().toList(); verify(service, never()).getFormData(any()); } + + private void setupMocks() { + var testFormData = FormDataTestFactory.create(); + when(mapper.toFormData(any(), any(), eq(vorgangNummerSupplier))).thenReturn(testFormData); + when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message); + } } @Nested - class TestFilterByMessageType { + class TestIsSupportedMessageType { @Test void shouldAcceptDFoerdermittel() { var metaDataDFoerder = XtaMessageMetaDataTestFactory.create(); - assertThat(service.filterByMessageType(metaDataDFoerder)).isTrue(); + assertThat(service.isSupportedMessageType(metaDataDFoerder)).isTrue(); } @Test void shouldNotAcceptOtherMessageType() { var metaDataDFoerder = XtaMessageMetaDataTestFactory.createBuilder().messageType(MESSAGE_TYPE_OTHER).build(); - assertThat(service.filterByMessageType(metaDataDFoerder)).isFalse(); + assertThat(service.isSupportedMessageType(metaDataDFoerder)).isFalse(); } } @Nested class TestGetFormData { - private XtaMessage message = XtaMessageTestFactory.create(); + private XtaMessage message; + private XdomeaMessageData classification; + + @Captor + private ArgumentCaptor<XtaMessageMetaData> messageMetaDataCaptor; @Captor - private ArgumentCaptor<XtaMessage> messageCaptor; - @Mock - private FormData formData; + private ArgumentCaptor<XdomeaMessageData> classificationCaptor; @BeforeEach void init() { + message = XtaMessageTestFactory.create(); when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message); + + classification = XdomeaMessageDataTestFactory.create(); + var incomingFiles = List.of(IncomingFileTestFactory.create(), IncomingFileTestFactory.create()); + when(incomingFilesMapper.toIncomingFiles(message.getMessageFiles())).thenReturn(incomingFiles); + classification = XdomeaMessageDataTestFactory.create(); + when(xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles)).thenReturn(classification); } @Test void shouldCallRemoteService() { - doReturn(formData).when(service).updateHeader(any()); - service.getFormData(XtaMessageMetaDataTestFactory.create()); verify(remoteService).getMessage(XtaMessageTestFactory.MESSAGE_ID); @@ -128,29 +147,26 @@ class XtaServiceTest { @Test void shouldCallMapper() { - doReturn(formData).when(service).updateHeader(any()); - service.getFormData(XtaMessageMetaDataTestFactory.create()); - verify(mapper).toFormData(any()); + verify(mapper).toFormData(any(), any(), eq(vorgangNummerSupplier)); } @Test void shouldHaveMetaData() { - doReturn(formData).when(service).updateHeader(any()); XtaMessageMetaData metaData = XtaMessageMetaDataTestFactory.create(); service.getFormData(metaData); - verify(mapper).toFormData(messageCaptor.capture()); - assertThat(messageCaptor.getValue().getMetaData()).isNotNull().isEqualTo(metaData); + verify(mapper).toFormData(classificationCaptor.capture(), messageMetaDataCaptor.capture(), eq(vorgangNummerSupplier)); + assertThat(messageMetaDataCaptor.getValue()).isEqualTo(metaData); + assertThat(classificationCaptor.getValue()).isEqualTo(classification); } @Test void shouldReturnMappedResult() { var mapped = FormDataTestFactory.create(); - when(mapper.toFormData(any())).thenReturn(mapped); - doReturn(mapped).when(service).updateHeader(any()); + when(mapper.toFormData(any(), any(), eq(vorgangNummerSupplier))).thenReturn(mapped); var result = service.getFormData(XtaMessageMetaDataTestFactory.create()); @@ -158,50 +174,6 @@ class XtaServiceTest { } } - @Nested - class TestUpdateHeader { - - @Test - void shouldCallSetVorgangNummer() { - var formData = FormDataTestFactory.create(); - - service.updateHeader(formData); - - verify(service).setVorgangNummer(formData.getHeader()); - } - - @Test - void shouldSetUpdatedHeader() { - var updatedHeader = FormHeaderTestFactory.create(); - doReturn(updatedHeader).when(service).setVorgangNummer(any()); - - var result = service.updateHeader(FormDataTestFactory.create()); - - Assertions.assertThat(result.getHeader()).isSameAs(updatedHeader); - } - } - - @Nested - class TestSetVorgangNummer { - - @Test - void shouldCallVorgangNummerSupplier() { - service.setVorgangNummer(FormHeaderTestFactory.create()); - - verify(vorgangNummerSupplier).get(XtaService.VORGANG_NUMMER_SUFFIX_LENGTH); - } - - @Test - void shouldSetVorgangNummer() { - var vorgangNummer = "vorgang-1"; - when(vorgangNummerSupplier.get(anyInt())).thenReturn(vorgangNummer); - - var result = service.setVorgangNummer(FormHeaderTestFactory.create()); - - assertThat(result.getVorgangNummer()).isEqualTo(vorgangNummer); - } - } - @Nested class TestAcknowledgeReceive { diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/LimitedInputStreamTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/LimitedInputStreamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b01c316d94f4bc994601401daaabacb4e0134efc --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/LimitedInputStreamTest.java @@ -0,0 +1,141 @@ +package de.ozgcloud.eingang.xta.zip; + +import static de.ozgcloud.eingang.xta.zip.LimitedInputStream.*; +import static org.assertj.core.api.Assertions.*; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +import org.apache.commons.io.IOUtils; +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 lombok.SneakyThrows; + +class LimitedInputStreamTest { + + private static final int READ_LIMIT = 10; + private static final String STRING_WITH_READ_LIMIT_LENGTH = "A".repeat(READ_LIMIT); + private static final String STRING_WITH_MORE_THAN_READ_LIMIT_LENGTH = "B".repeat(READ_LIMIT + 1); + + private LimitedInputStream limitedInputStream; + + private InputStream createStringInputSteam(String string) { + return new ByteArrayInputStream(string.getBytes()); + } + + @SneakyThrows + private String readInputStreamToString(InputStream inputStream) { + return IOUtils.toString(inputStream, Charset.defaultCharset()); + } + + @SneakyThrows + @DisplayName("should succeed if read limit is not exceeded") + @Test + void shouldSucceedIfReadLimitIsNotExceeded() { + limitedInputStream = new LimitedInputStream(createStringInputSteam(STRING_WITH_READ_LIMIT_LENGTH), READ_LIMIT); + + var outputString = readInputStreamToString(limitedInputStream); + + assertThat(outputString).isEqualTo(STRING_WITH_READ_LIMIT_LENGTH); + } + + @DisplayName("should fail if read limit is exceeded") + @Test + void shouldFailIfReadLimitIsExceeded() { + limitedInputStream = new LimitedInputStream(createStringInputSteam(STRING_WITH_MORE_THAN_READ_LIMIT_LENGTH), READ_LIMIT); + + assertThatThrownBy(() -> readInputStreamToString(limitedInputStream)) + .isInstanceOf(IOException.class) + .hasMessage(LIMITED_EXCEEDED_MESSAGE); + } + + @DisplayName("read") + @Nested + class TestRead { + + @SneakyThrows + @DisplayName("should return") + @Test + void shouldReturn() { + limitedInputStream = createLimitedInputStream(); + + var result = limitedInputStream.read(); + assertThat(result).isEqualTo(STRING_WITH_READ_LIMIT_LENGTH.getBytes()[0]); + } + + @SneakyThrows + @DisplayName("should advance bytesRead") + @Test + void shouldAdvanceBytesRead() { + limitedInputStream = createLimitedInputStream(); + limitedInputStream.bytesRead = READ_LIMIT - 1; + + limitedInputStream.read(); + assertThat(limitedInputStream.bytesRead).isEqualTo(READ_LIMIT); + } + + @DisplayName("should throw if exceeded") + @Test + void shouldThrowIfExceeded() { + limitedInputStream = createLimitedInputStreamWithExceeding(); + limitedInputStream.bytesRead = READ_LIMIT; + + assertThatThrownBy(() -> limitedInputStream.read()).isInstanceOf(IOException.class); + } + + } + + @DisplayName("read into buffer") + @Nested + class TestReadIntoBuffer { + private byte[] buffer; + + @BeforeEach + void mock() { + buffer = new byte[READ_LIMIT]; + } + + @SneakyThrows + @DisplayName("should return") + @Test + void shouldReturn() { + limitedInputStream = createLimitedInputStream(); + + var result = limitedInputStream.read(buffer); + + assertThat(result).isEqualTo(READ_LIMIT); + } + + @SneakyThrows + @DisplayName("should advance bytesRead") + @Test + void shouldAdvanceBytesRead() { + limitedInputStream = createLimitedInputStream(); + + limitedInputStream.read(buffer); + assertThat(limitedInputStream.bytesRead).isEqualTo(READ_LIMIT); + } + + @DisplayName("should throw if exceeded") + @Test + void shouldThrowIfExceeded() { + limitedInputStream = createLimitedInputStreamWithExceeding(); + limitedInputStream.bytesRead = 1; + + assertThatThrownBy(() -> limitedInputStream.read(buffer)).isInstanceOf(IOException.class); + } + } + + private LimitedInputStream createLimitedInputStream() { + return new LimitedInputStream(createStringInputSteam(STRING_WITH_READ_LIMIT_LENGTH), READ_LIMIT); + } + + private LimitedInputStream createLimitedInputStreamWithExceeding() { + return new LimitedInputStream(createStringInputSteam(STRING_WITH_MORE_THAN_READ_LIMIT_LENGTH), READ_LIMIT); + } +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntryTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e5bfea0888cf15d8791777a8bf826e13868c489c --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntryTest.java @@ -0,0 +1,80 @@ +package de.ozgcloud.eingang.xta.zip; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +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.Mock; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import lombok.SneakyThrows; + +class ReadableZipEntryTest { + + @Mock + ZipEntry zipEntry; + + @Mock + ZipFile zipFile; + + private ReadableZipEntry readableZipEntry; + + @BeforeEach + void mock() { + readableZipEntry = ReadableZipEntry.builder() + .zipEntry(zipEntry) + .parentZip(zipFile) + .build(); + + } + + @DisplayName("get input stream") + @Nested + class TestGetInputStream { + @Mock + private InputStream inputStream; + + @SneakyThrows + @DisplayName("should return input stream") + @Test + void shouldReturnInputStream() { + when(zipFile.getInputStream(zipEntry)).thenReturn(inputStream); + + var inputStreamResult = readableZipEntry.getInputStream(); + + assertThat(inputStreamResult).isEqualTo(inputStream); + } + } + + @DisplayName("get positive size") + @Nested + class TestGetPositiveSize { + @DisplayName("should return size") + @Test + void shouldReturnSize() { + var size = 123L; + when(zipEntry.getSize()).thenReturn(size); + + var sizeResult = readableZipEntry.getPositiveSize(); + + assertThat(sizeResult).isEqualTo(size); + } + + @DisplayName("should throw if size is negative") + @Test + void shouldThrowIfSizeIsNegative() { + var size = -1L; + when(zipEntry.getSize()).thenReturn(size); + + assertThatThrownBy(() -> readableZipEntry.getPositiveSize()).isInstanceOf(TechnicalException.class); + } + + } +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/TestZipFileFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/TestZipFileFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..8ac1b3595af4ae63e720a765d8fdced3a9730906 --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/TestZipFileFactory.java @@ -0,0 +1,113 @@ +package de.ozgcloud.eingang.xta.zip; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.apache.commons.io.IOUtils; + +import de.ozgcloud.common.binaryfile.TempFileUtils; +import lombok.Builder; +import lombok.Getter; + +public class TestZipFileFactory { + + private static final String EXPANDED_ENTRY_NAME = "bomb.txt"; + + @Builder + @Getter + public static class TestZipEntry { + private String name; + private byte[] content; + } + + public static File createTempZipFile(List<TestZipEntry> testZipEntries) { + var file = TempFileUtils.createTmpFile().toFile(); + try (var zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) { + for (TestZipEntry entry : testZipEntries) { + zipOutputStream.putNextEntry(new ZipEntry(entry.getName())); + zipOutputStream.write(entry.getContent()); + zipOutputStream.closeEntry(); + } + return file; + } catch (IOException e) { + throw new RuntimeException("Failed to create temporary zip file", e); + } + } + + public static File createTempZipBomb(int maxTotalSize) { + return overwriteFileWithZipEntrySize( + createTempZipWithSingleEntry(maxTotalSize * 2), + maxTotalSize + ); + } + + private static File createTempZipWithSingleEntry(int entrySize) { + var file = TempFileUtils.createTmpFile().toFile(); + try (var zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) { + var entry = new ZipEntry(EXPANDED_ENTRY_NAME); + var content = "A".repeat(entrySize).getBytes(); + + zipOutputStream.putNextEntry(entry); + zipOutputStream.write(content); + zipOutputStream.closeEntry(); + + } catch (IOException e) { + throw new RuntimeException("Failed to create temporary zip file", e); + } + return file; + } + + private static File overwriteFileWithZipEntrySize(File file, int newSize) { + try { + var zipFileBytes = IOUtils.toByteArray(new FileInputStream(file)); + overwriteZipEntrySize(zipFileBytes, EXPANDED_ENTRY_NAME, newSize); + + // Write the adjusted ZIP content back to the file + try (var fos = new FileOutputStream(file)) { + fos.write(zipFileBytes); + } + } catch (IOException e) { + throw new RuntimeException("Failed to adjust size header of zip file", e); + } + return file; + } + + private static void overwriteZipEntrySize(byte[] zipFileBytes, String entryName, int newSize) throws IOException { + // Modify the uncompressed size entry size in the central directory structure (which is located at the end) + // Zip structure spec: https://www.iana.org/assignments/media-types/application/zip + var entryNameBytes = entryName.getBytes(); + + var lastIndexOfEntryName = findLastStartIndex(zipFileBytes, entryNameBytes); + if (lastIndexOfEntryName == -1) { + throw new IOException("ZIP entry not found: " + entryName); + } + var uncompressedSizeFieldStartOffset = lastIndexOfEntryName - (4 * 2 + 5 * 2 + 4); + writeIntToByteArray(newSize, zipFileBytes, uncompressedSizeFieldStartOffset); + } + + private static void writeIntToByteArray(int value, byte[] array, int offset) { + array[offset] = (byte) (value & 0xFF); + array[offset + 1] = (byte) ((value >> 8) & 0xFF); + array[offset + 2] = (byte) ((value >> 16) & 0xFF); + array[offset + 3] = (byte) ((value >> 24) & 0xFF); + } + + private static int findLastStartIndex(byte[] haystack, byte[] needle) { + var matchOffset = 0; + for (var i = haystack.length - 1; i >= needle.length; i--) { + if (haystack[i] == needle[needle.length - 1 - matchOffset]) { + if (++matchOffset == needle.length) { + return i; + } + } else { + matchOffset = 0; + } + } + return -1; + } +} diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractorTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d23838973567f333510c7b14d5ae4536cd119655 --- /dev/null +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractorTest.java @@ -0,0 +1,371 @@ +package de.ozgcloud.eingang.xta.zip; + +import static de.ozgcloud.eingang.xta.zip.TestZipFileFactory.*; +import static de.ozgcloud.eingang.xta.zip.ZipFileExtractor.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import java.util.zip.ZipEntry; + +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.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.util.MimeTypeUtils; + +import de.ozgcloud.eingang.common.errorhandling.TechnicalException; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import lombok.SneakyThrows; + +class ZipFileExtractorTest { + + @Spy + @InjectMocks + private ZipFileExtractor extractor; + + @DisplayName("extract incoming files safely") + @Nested + class TestExtractIncomingFilesWithSizeLimit { + @Mock + IncomingFile incomingZipFile; + + @Mock + File zipFile; + + @Mock + IncomingFile outIncomingFile; + + List<IncomingFile> outIncomingFiles; + + @BeforeEach + void mock() { + outIncomingFiles = List.of(outIncomingFile); + + when(incomingZipFile.getFile()).thenReturn(zipFile); + doNothing().when(extractor).verifyLimits(zipFile); + + doReturn(outIncomingFiles).when(extractor).extractIncomingFiles(zipFile); + } + + @DisplayName("should call verify limits") + @Test + void shouldCallVerifySizeLimit() { + extractor.extractIncomingFilesSafely(incomingZipFile); + + verify(extractor).verifyLimits(zipFile); + } + + @DisplayName("should return") + @Test + void shouldReturn() { + var output = extractor.extractIncomingFilesSafely(incomingZipFile); + + assertThat(output).isEqualTo(outIncomingFiles); + } + } + + @DisplayName("verify limits") + @Nested + class TestVerifyLimits { + @Mock + File zipFile; + + @DisplayName("should return") + @Test + void shouldReturn() { + when(zipFile.length()).thenReturn((long) ZIP_MAX_TOTAL_SIZE / 2); + doReturn((long) ZIP_MAX_TOTAL_SIZE).when(extractor).sumUncompressedEntrySizes(zipFile); + + extractor.verifyLimits(zipFile); + } + + @DisplayName("should throw if size limit exceeded") + @Test + void shouldThrowIfSizeLimitExceeded() { + doReturn((long) ZIP_MAX_TOTAL_SIZE + 1).when(extractor).sumUncompressedEntrySizes(zipFile); + + assertThatThrownBy(() -> extractor.verifyLimits(zipFile)) + .isInstanceOf(TechnicalException.class); + } + + @DisplayName("should throw if ratio exceeded") + @Test + void shouldThrowIfRatioExceeded() { + when(zipFile.length()).thenReturn(1L); + doReturn((long) ZIP_MAX_THRESHOLD + 1).when(extractor).sumUncompressedEntrySizes(zipFile); + + assertThatThrownBy(() -> extractor.verifyLimits(zipFile)) + .isInstanceOf(TechnicalException.class); + } + } + + @DisplayName("extract incoming files") + @Nested + class TestExtractIncomingFiles { + + private File zipFile; + + @BeforeEach + void mock() { + zipFile = createTempZipFile(fromMap(Map.of( + "file1.pdf", "file content1", + "file2.xml", "<root></root>", + "file3.png", "" + ))); + } + + @DisplayName("should contain content") + @Test + void shouldContainContent() { + var extractedFiles = extractor.extractIncomingFiles(zipFile); + + var contents = extractedFiles.stream().map(f -> { + try { + return Files.readString(f.getFile().toPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }).toList(); + assertThat(contents).containsExactlyInAnyOrder("file content1", "<root></root>", ""); + } + + @DisplayName("should have names") + @Test + void shouldHaveNames() { + var extractedFiles = extractor.extractIncomingFiles(zipFile); + + var names = extractedFiles.stream().map(IncomingFile::getName).toList(); + assertThat(names).containsExactlyInAnyOrder("file1.pdf", "file2.xml", "file3.png"); + } + + @DisplayName("should have content types") + @Test + void shouldHaveContentTypes() { + var extractedFiles = extractor.extractIncomingFiles(zipFile); + + var names = extractedFiles.stream().map(IncomingFile::getContentType).toList(); + assertThat(names).containsExactlyInAnyOrder("application/pdf", "application/xml", "image/png"); + } + + private List<TestZipEntry> fromMap(Map<String, String> entries) { + return entries.entrySet().stream().map(kv -> TestZipEntry.builder() + .name(kv.getKey()) + .content(kv.getValue().getBytes(StandardCharsets.UTF_8)) + .build()) + .toList(); + } + } + + @DisplayName("extract zip bomb") + @Nested + class TestExtractZipBomb { + private static final int SMALLER_MAX_ZIP_FILE_SIZE = 2 * 1024; + + @DisplayName("should throw with too many entries") + @Test + void shouldThrow() { + var zipFile = createIncomingFile(createTempZipFile(IntStream.range(0, ZIP_MAX_ENTRIES + 1).mapToObj(i -> TestZipEntry.builder() + .name("file%d.txt".formatted(i)) + .content(toBytes("A".repeat(2))) + .build() + ).toList())); + + assertThatThrownBy(() -> extractor.extractIncomingFilesSafely(zipFile)) + .isInstanceOf(TechnicalException.class); + } + + @SneakyThrows + @DisplayName("should throw with fake getSize") + @Test + void shouldThrowWithFakeGetSize() { + doReturn(SMALLER_MAX_ZIP_FILE_SIZE).when(extractor).getZipMaxTotalSize(); + var zipBomb = createIncomingFile(createTempZipBomb(SMALLER_MAX_ZIP_FILE_SIZE)); + + assertThatThrownBy(() -> extractor.extractIncomingFilesSafely(zipBomb)) + .isInstanceOf(TechnicalException.class) + .hasRootCauseMessage(LimitedInputStream.LIMITED_EXCEEDED_MESSAGE); + } + + @DisplayName("should throw with too large size") + @Test + void shouldThrowWithTooLargeSize() { + doReturn(SMALLER_MAX_ZIP_FILE_SIZE).when(extractor).getZipMaxTotalSize(); + var zipFile = createIncomingFile(createTempZipFile(List.of(TestZipEntry.builder() + .name("toolargefile.txt") + .content(toBytes("A".repeat(SMALLER_MAX_ZIP_FILE_SIZE + 1))) + .build() + ))); + + assertThatThrownBy(() -> extractor.extractIncomingFilesSafely(zipFile)) + .isInstanceOf(TechnicalException.class); + } + + private IncomingFile createIncomingFile(File file) { + return IncomingFile.builder() + .file(file) + .build(); + } + } + + @DisplayName("create incoming file") + @Nested + class TestCreateIncomingFile { + @Mock + File file; + + @Mock + ZipEntry zipEntry; + + private static final String NAME = "filename.name"; + private static final Long SIZE = 5L; + private static final String CONTENT_TYPE = "some/content"; + + @BeforeEach + void mock() { + when(zipEntry.getName()).thenReturn(NAME); + when(zipEntry.getSize()).thenReturn(SIZE); + doReturn(CONTENT_TYPE).when(extractor).getContentType(NAME); + } + + @DisplayName("should have name") + @Test + void shouldHaveName() { + var incomingFile = create(); + + assertThat(incomingFile.getName()).isEqualTo(NAME); + } + + @DisplayName("should have size") + @Test + void shouldHaveSize() { + var incomingFile = create(); + + assertThat(incomingFile.getSize()).isEqualTo(SIZE); + } + + @DisplayName("should have content type") + @Test + void shouldHaveContentType() { + var incomingFile = create(); + + assertThat(incomingFile.getContentType()).isEqualTo(CONTENT_TYPE); + } + + @DisplayName("should have file") + @Test + void shouldHaveFile() { + var incomingFile = create(); + + assertThat(incomingFile.getFile()).isEqualTo(file); + } + + private IncomingFile create() { + return extractor.createIncomingFile(file, zipEntry); + } + } + + @DisplayName("sum uncompressed entry size") + @Nested + class TestSumUncompressedEntrySize { + @DisplayName("should return size") + @Test + void shouldReturnSize() { + var sizes = IntStream.range(100, 110).boxed().toList(); + var expectedSum = sizes.stream().mapToLong(Integer::longValue).sum(); + var zipFile = createTempZipFile(sizes.stream() + .map(size -> TestZipEntry.builder() + .name("somefilewithsize%d".formatted(size)) + .content(toBytes("A".repeat(size))) + .build() + ).toList()); + + var sum = extractor.sumUncompressedEntrySizes(zipFile); + + assertThat(sum).isEqualTo(expectedSum); + } + } + + @Nested + class TestContentType { + + @Test + void shouldReturnDefaultWhenNullString() { + assertThrows(NullPointerException.class, () -> extractor.getContentType(null)); + } + + @Test + void shouldReturnDefaultWhenEmptyString() { + var contentType = extractor.getContentType(StringUtils.EMPTY); + + assertThat(contentType).isEqualTo(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE); + } + + @Test + void shouldReturnDefaultWhenSpaceString() { + var contentType = extractor.getContentType(StringUtils.SPACE); + + assertThat(contentType).isEqualTo(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE); + } + + @Test + void shouldGetContentType() { + var fileNames = List.of("1.xml", "2.txt"); + + var contentTypes = fileNames.stream().map(extractor::getContentType).toList(); + + assertThat(contentTypes).containsExactlyInAnyOrder(MimeTypeUtils.APPLICATION_XML_VALUE, MimeTypeUtils.TEXT_PLAIN_VALUE); + } + } + + @DisplayName("map zip entries") + @Nested + class TestMapZipEntries { + + @DisplayName("should throw if max entries exceeded") + @Test + void shouldThrowIfMaxEntriesExceeded() { + var zipWithTooManyEntries = createTempZipFile(IntStream.range(0, ZIP_MAX_ENTRIES + 1) + .mapToObj(i -> TestZipEntry.builder() + .name("test%d.txt".formatted(i)) + .content(toBytes("test file %d".formatted(i))) + .build() + ).toList()); + + assertThatThrownBy(() -> extractor.mapZipEntries(zipWithTooManyEntries, entry -> null)) + .isInstanceOf(TechnicalException.class); + } + + @DisplayName("should map with mapping function") + @Test + void shouldMapWithMappingFunction() { + var expectedNumberList = IntStream.range(0, ZIP_MAX_ENTRIES).boxed().toList(); + var zipFile = createTempZipFile(expectedNumberList.stream() + .map(i -> TestZipEntry.builder() + .name("%d".formatted(i)) + .content(toBytes("some content")) + .build() + ).toList()); + + var numberList = extractor.mapZipEntries(zipFile, entry -> Integer.parseInt(entry.getName())); + + assertThat(numberList).isEqualTo(expectedNumberList); + } + } + + private byte[] toBytes(String string) { + return string.getBytes(StandardCharsets.UTF_8); + } + +} diff --git a/xta-adapter/src/test/resources/application-itcase.yml b/xta-adapter/src/test/resources/application-itcase.yml index 10c37fce51476732675a22abedd6ec6257d726f6..99b88fbe12ffdb4562dc264c08595afde1b9092a 100644 --- a/xta-adapter/src/test/resources/application-itcase.yml +++ b/xta-adapter/src/test/resources/application-itcase.yml @@ -1,6 +1,21 @@ ozgcloud: xta: + identifier: afmsh:010600000000_Online-Dienste + server: + address: localhost:3000 + name: LI33-0005 + protocol: https keystore: file: classpath:xtaTestStore.p12 password: changeit - identifier: gae:jens.reese@mgm-tp.com \ No newline at end of file + adapter: + targetVorgangManagerName: itcase + fallbackStrategy: DENY + routingStrategy: SINGLE + + +grpc: + client: + vorgang-manager-itcase: + address: in-process:vorgang-manager-itcase + negotiationType: PLAINTEXT diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/2ef19b50-2d00-4cb0-8318-e3422ab27b86_PDF-Antrag.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/2ef19b50-2d00-4cb0-8318-e3422ab27b86_PDF-Antrag.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4e6e6bf6da699a082d70749f5d383163c4e05373 Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/2ef19b50-2d00-4cb0-8318-e3422ab27b86_PDF-Antrag.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/4bb895cc-7b60-4322-81fa-cf928d1a22e5_00TESTPDF.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/4bb895cc-7b60-4322-81fa-cf928d1a22e5_00TESTPDF.pdf new file mode 100644 index 0000000000000000000000000000000000000000..faf48ce9c5f7854d8cab8825be92d6ee2e23843f Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/4bb895cc-7b60-4322-81fa-cf928d1a22e5_00TESTPDF.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/60b6753a-23a8-4552-ae82-36ed96f63e03_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/60b6753a-23a8-4552-ae82-36ed96f63e03_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..9623996ed13c169c65fdc7b49b98671a4ce5f6ee --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/60b6753a-23a8-4552-ae82-36ed96f63e03_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,107 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>60b6753a-23a8-4552-ae82-36ed96f63e03</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Nachrichtentyp">0201</xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-05-17T15:35:54.560+02:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Schleswig-Holstein</xdomea:Name> + <xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001 ">ozg-cloud-dev001 </xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>30714b70-3ba3-4f32-a36a-4990162f14bb</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Brauchtumsfeuer NB Anbindung Test</xdomea:Betreff> + <xdomea:Kennzeichen>20240517561130590306</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-05-17</xdomea:Posteingangsdatum> + <xdomea:Typ>btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + <xdomea:Version> + <xdomea:Nummer>0.0</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>2ef19b50-2d00-4cb0-8318-e3422ab27b86_PDF-Antrag.pdf</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>6c89a915-791b-4e9f-a06b-a23a16925c34</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001</xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001 ">ozg-cloud-dev001 </xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-05-17</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>15:35:54</xdomea:Erstellungsuhrzeit> + </xdomea:Verfuegung> + </xdomea:Beteiligungsschritt> + </xdomea:ExternerGeschaeftsgang> + <xdomea:Anlage> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>44d72e8a-f8e3-484b-bf0c-a84cf1aebe0c</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Typ>Anlage</xdomea:Typ> + <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>4bb895cc-7b60-4322-81fa-cf928d1a22e5_00TESTPDF.pdf</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Anlage> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201> \ No newline at end of file diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml new file mode 100644 index 0000000000000000000000000000000000000000..0ef5e29a104eaec8e9585d2649859c0cce1cc751 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" t:form-version="2.022" + t:uuid="a1d537b5-79f1-492b-8966-b66d391fe294" t:id="20240517561130590306" t:timestamp="2024-05-17T13:35:13.586Z" + t:sender="test.afm.schleswig-holstein.de" t:form="Brauchtumsfeuer NB Anbindung Test" + t:form-id="btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb" t:customer="Schleswig-Holstein" t:customer-id="sh" + t:client="Schleswig-Holstein" t:client-id="land" t:lang="de-DE"> + <GebietID>9006880</GebietID> + <AnliegenID>9552000</AnliegenID> + <GebietBEZEICHNUNG>Scharbeutz</GebietBEZEICHNUNG> + <zst_online_dienst>Brauchtumsfeuer: + Anmeldung;266889711;https://www.dataport.de/datenschutz/;WEBSERVICE;;;https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas;https://www.dataport.de/impressum/;true + </zst_online_dienst> + <datenschutz_akzeptiert>true</datenschutz_akzeptiert> + <zustaendigestelle> + <OrganisationseinheitenID>9795669</OrganisationseinheitenID> + </zustaendigestelle> + <OrganisationseinheitenBEZEICHNUNG>Dataport-AFM-SH-Entwicklung Kunstbehörde</OrganisationseinheitenBEZEICHNUNG> + <zust_kontaktsystemkennung_ln /> + <zust_kontaktsystemkennung_nb /> + <zust_kontaktsystemkennung_webservice>https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas + </zust_kontaktsystemkennung_webservice> + <zust_strasse>Entwicklerweg</zust_strasse> + <zust_hausnummer>123</zust_hausnummer> + <zust_postleitzahl>24107</zust_postleitzahl> + <ortID>9006402</ortID> + <zust_ort>Kiel</zust_ort> + <zust_telefonnummer>+49 40 42846-4032</zust_telefonnummer> + <zust_faxnummer /> + <zust_emailadresse>Ramin.Jeyrani@dataport.de</zust_emailadresse> + <anzeigender_verantwortlich>true</anzeigender_verantwortlich> + <anzeigender_nachname>mit Anhang</anzeigender_nachname> + <anzeigender_vorname>Test</anzeigender_vorname> + <anzeigender_geburtsdatum>2001-01-01</anzeigender_geburtsdatum> + <anzeigender_land_auswahl>in Deutschland</anzeigender_land_auswahl> + <anzeigender_strasse>Test</anzeigender_strasse> + <anzeigender_hausnummer>1</anzeigender_hausnummer> + <anzeigender_postleitzahl>22222</anzeigender_postleitzahl> + <anzeigender_ort>Test</anzeigender_ort> + <anzeigender_firma /> + <kontakt_mail>malte.jendroschek@dataport.de</kontakt_mail> + <kontakt_telefon /> + <kontakt_mobil /> + <verantwortlicher_mobil>0123456789</verantwortlicher_mobil> + <verantwortlicher_mobil2 /> + <angabe>adresse</angabe> + <strasse>Teststr</strasse> + <hausnummer>1</hausnummer> + <ort>Scharbeutz</ort> + <ortsteil /> + <angaben_extra /> + <lageplan> + <file content-type="application/pdf" description="" id="assistants.85D54E9431CF70430ACBB8DD3E604E83C03B1891" + length="185689">00TESTPDF.pdf + </file> + </lageplan> + <feuer_datum>2025-07-08</feuer_datum> + <feuer_start>15:00</feuer_start> + <feuer_ende>23:00</feuer_ende> + <feuer_groesse>1000</feuer_groesse> + <feuer_art>Alles + </feuer_art> + <feuer_gefahrenabwehr /> + <weitergabe>true</weitergabe> + <richtigkeit>true</richtigkeit> + <missbrauch>true</missbrauch> + <betreff>Anzeige eines Brauchtumsfeuers</betreff> + <nachricht>Sehr geehrte/r Angtragssteller/in<br/><br/>Ihr Antrag wurde an die zuständige Stelle + gesendet.<br/> Ihre Vorgangsnummer und zuständige Stelle finden Sie im angehängten Dokument. <br/>Bitte + geben Sie diese Vorgangsnummer bei allen Anfragen zu Ihrerm Antrag an.<br/><br/><br/>Mit + freundlichen Grüßen<br/><br/>Ihre zuständige Stelle + </nachricht> + <mail /> + <nameid /> + <rest_response_name>[]</rest_response_name> + <mailboxguid /> + <antragsteller> + <pers_anrede /> + <pers_nachname>mit Anhang</pers_nachname> + <pers_vorname>Test</pers_vorname> + <pers_geburtsdatum>2001-01-01</pers_geburtsdatum> + <sh_strasse>Test</sh_strasse> + <sh_hausnummer>1</sh_hausnummer> + <sh_plz>22222</sh_plz> + <ort>Test</ort> + <kont_telefonnummer /> + <kont_mobilnummer /> + <kont_email>malte.jendroschek@dataport.de</kont_email> + </antragsteller> +</myForm> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..e66b92187f6db6335ea86ea32f127d78f70cd786 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,89 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Nachrichtentyp">0201</xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-05-17T09:21:09.073+02:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Schleswig-Holstein</xdomea:Name> + <xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>e8f627fe-b90c-4fc7-ba61-20a43041971b</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Brauchtumsfeuer NB Anbindung Test</xdomea:Betreff> + <xdomea:Kennzeichen>20240517335360945504</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-05-17</xdomea:Posteingangsdatum> + <xdomea:Typ>btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + <xdomea:Version> + <xdomea:Nummer>0.0</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>3a41cc59-baf4-424d-8c69-a8e7f7470d68_PDF-Antrag.pdf</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>f5966df2-633a-4763-a769-b4250d66df58</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001</xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-05-17</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>09:21:06</xdomea:Erstellungsuhrzeit> + </xdomea:Verfuegung> + </xdomea:Beteiligungsschritt> + </xdomea:ExternerGeschaeftsgang> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201> \ No newline at end of file diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/3a41cc59-baf4-424d-8c69-a8e7f7470d68_PDF-Antrag.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/3a41cc59-baf4-424d-8c69-a8e7f7470d68_PDF-Antrag.pdf new file mode 100644 index 0000000000000000000000000000000000000000..484faac99dc6dd2f9f05e1abaa47f13f702cac19 Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/3a41cc59-baf4-424d-8c69-a8e7f7470d68_PDF-Antrag.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml new file mode 100644 index 0000000000000000000000000000000000000000..db0955a13f0d30a33b0ab4fb1f043d79b2868382 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" t:form-version="2.022" t:uuid="147839b0-e938-4606-a8bc-104afd83a2b3" t:id="20240517335360945504" t:timestamp="2024-05-17T07:18:56.031Z" t:sender="test.afm.schleswig-holstein.de" t:form="Brauchtumsfeuer NB Anbindung Test" t:form-id="btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb" t:customer="Schleswig-Holstein" t:customer-id="sh" t:client="Schleswig-Holstein" t:client-id="land" t:lang="de-DE"><GebietID>9006880</GebietID><AnliegenID>9552000</AnliegenID><GebietBEZEICHNUNG>Scharbeutz</GebietBEZEICHNUNG><zst_online_dienst>Brauchtumsfeuer: Anmeldung;266889711;https://www.dataport.de/datenschutz/;WEBSERVICE;;;https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas;https://www.dataport.de/impressum/;true</zst_online_dienst><datenschutz_akzeptiert>true</datenschutz_akzeptiert><zustaendigestelle><OrganisationseinheitenID>9795669</OrganisationseinheitenID></zustaendigestelle><OrganisationseinheitenBEZEICHNUNG>Dataport-AFM-SH-Entwicklung Kunstbehörde</OrganisationseinheitenBEZEICHNUNG><zust_kontaktsystemkennung_ln/><zust_kontaktsystemkennung_nb/><zust_kontaktsystemkennung_webservice>https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas</zust_kontaktsystemkennung_webservice><zust_strasse>Entwicklerweg</zust_strasse><zust_hausnummer>123</zust_hausnummer><zust_postleitzahl>24107</zust_postleitzahl><ortID>9006402</ortID><zust_ort>Kiel</zust_ort><zust_telefonnummer>+49 40 42846-4032</zust_telefonnummer><zust_faxnummer/><zust_emailadresse>Ramin.Jeyrani@dataport.de</zust_emailadresse><anzeigender_verantwortlich>true</anzeigender_verantwortlich><anzeigender_nachname>Malte</anzeigender_nachname><anzeigender_vorname>Test von</anzeigender_vorname><anzeigender_geburtsdatum>2001-01-01</anzeigender_geburtsdatum><anzeigender_land_auswahl>in Deutschland</anzeigender_land_auswahl><anzeigender_strasse>Teststraße</anzeigender_strasse><anzeigender_hausnummer>1</anzeigender_hausnummer><anzeigender_postleitzahl>22222</anzeigender_postleitzahl><anzeigender_ort>Teststadt</anzeigender_ort><anzeigender_firma/><kontakt_mail>malte.jendroschek@dataport.de</kontakt_mail><kontakt_telefon/><kontakt_mobil/><verantwortlicher_mobil>0123</verantwortlicher_mobil><verantwortlicher_mobil2/><angabe>adresse</angabe><strasse>Test</strasse><hausnummer>1</hausnummer><ort>Scharbeutz</ort><ortsteil/><angaben_extra/><feuer_datum>2024-10-01</feuer_datum><feuer_start>8:00</feuer_start><feuer_ende>12:00</feuer_ende><feuer_groesse>100</feuer_groesse><feuer_art>Holz +</feuer_art><feuer_gefahrenabwehr/><weitergabe>true</weitergabe><richtigkeit>true</richtigkeit><missbrauch>true</missbrauch><betreff>Anzeige eines Brauchtumsfeuers</betreff><nachricht>Sehr geehrte/r Angtragssteller/in<br/><br/>Ihr Antrag wurde an die zuständige Stelle gesendet.<br/> Ihre Vorgangsnummer und zuständige Stelle finden Sie im angehängten Dokument. <br/>Bitte geben Sie diese Vorgangsnummer bei allen Anfragen zu Ihrerm Antrag an.<br/><br/><br/>Mit freundlichen Grüßen<br/><br/>Ihre zuständige Stelle</nachricht><mail/><nameid/><rest_response_name>[]</rest_response_name><mailboxguid/><antragsteller><pers_anrede/><pers_nachname>Malte</pers_nachname><pers_vorname>Test von</pers_vorname><pers_geburtsdatum>2001-01-01</pers_geburtsdatum><sh_strasse>Teststraße</sh_strasse><sh_hausnummer>1</sh_hausnummer><sh_plz>22222</sh_plz><ort>Teststadt</ort><kont_telefonnummer/><kont_mobilnummer/><kont_email>malte.jendroschek@dataport.de</kont_email></antragsteller></myForm> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/06d36643-2883-4b74-9231-8dc7f2693af2_Zusammenfassung-01f903b0-c61e-429d-807f-5011d180c073.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/06d36643-2883-4b74-9231-8dc7f2693af2_Zusammenfassung-01f903b0-c61e-429d-807f-5011d180c073.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5ac687e093135486e303a1547f90f548c3d52f6d Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/06d36643-2883-4b74-9231-8dc7f2693af2_Zusammenfassung-01f903b0-c61e-429d-807f-5011d180c073.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec0d7a08d0be142997505dd5b6d13015054d5d5 Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml new file mode 100644 index 0000000000000000000000000000000000000000..14aa5016cdef7d7a084f7e7f83b3be12e24d99da --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.dataport.de/dFAD/ApplicationDataMessageSchema"> + <ApplicationFormId>08dc645c-6704-48e7-868c-6afa8510384c</ApplicationFormId> + <Timestamp>2024-04-24T16:32:54.696248+02:00</Timestamp> + <ApplicationDataMessageVersion>3</ApplicationDataMessageVersion> + <Title>OZG-Cloud Test 2.0</Title> + <ProjectName>OZG-Cloud Test 2.0</ProjectName> + <ProjectTitle>OZG-Cloud Test 2.0</ProjectTitle> + <TransmittedApplicationId>UGLAG4ILLpz6a0</TransmittedApplicationId> + <MetaText1>9795669</MetaText1> + <InboxReference>hh/hh/4dd01647-b9d9-4775-1b50-08da3d83800a</InboxReference> + <AuthenticationAccountType>ServicekontoBasic</AuthenticationAccountType> + <AuthenticationMethod>UsernameAndPassword</AuthenticationMethod> + <AuthenticationIdentityDetails xsi:nil="true" /> + <Pages> + <Page> + <Title>Willkommen auf Ihrer neuen Seite</Title> + <Navigation>Freimodul 1</Navigation> + <Controls> + <Control> + <Upload> + <Label>Dateiupload</Label> + <Alias /> + <Files> + <Name>Admin.png</Name> + </Files> + </Upload> + </Control> + </Controls> + </Page> + </Pages> +</application> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/b29d45cc-9aac-4452-ad08-60f5ab3bab95_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/b29d45cc-9aac-4452-ad08-60f5ab3bab95_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..021987e3a06b61d8f509507c6cb9cac5ae4c8e44 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/b29d45cc-9aac-4452-ad08-60f5ab3bab95_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="utf-8"?> +<Geschaeftsgang.Geschaeftsgang.0201 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="urn:xoev-de:xdomea:schema:2.4.0 xdomea-Nachrichten-VBS.xsd" xmlns="urn:xoev-de:xdomea:schema:2.4.0"> + <Kopf> + <ProzessID>b29d45cc-9aac-4452-ad08-60f5ab3bab95</ProzessID> + <Nachrichtentyp listURI="urn:xoev-de:xdomea:codeliste:nachrichtentyp" listVersionID="1.0"> + <code xmlns="">0201</code> + </Nachrichtentyp> + <Erstellungszeitpunkt>2024-04-24T16:32:54.7247984+02:00</Erstellungszeitpunkt> + <Absender> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">010200200000</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gad</code> + </Praefix> + </Behoerdenkennung> + </Absender> + <Empfaenger> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">dev-environment@ozg-cloud.de</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gae</code> + </Praefix> + </Behoerdenkennung> + </Empfaenger> + <SendendesSystem> + <InstanzID>HH_dFoerdermittelantrag</InstanzID> + <Produktname>dFoerdermittelantrag</Produktname> + <Version>2.1.999.0</Version> + </SendendesSystem> + <EmpfangsbestaetigungAnInitiator>false</EmpfangsbestaetigungAnInitiator> + <EmpfangsbestaetigungAnVorgaenger>false</EmpfangsbestaetigungAnVorgaenger> + </Kopf> + <Hauptobjekt> + <Dokument> + <Identifikation> + <ID>5d142b11-7b52-4bfc-b14d-8d02fee84aa3</ID> + </Identifikation> + <AllgemeineMetadaten> + <Betreff>OZG-Cloud Test 2.0</Betreff> + <Kennzeichen>08dc645c-6704-48e7-868c-6afa8510384c</Kennzeichen> + </AllgemeineMetadaten> + <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>3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml</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>06d36643-2883-4b74-9231-8dc7f2693af2_Zusammenfassung-01f903b0-c61e-429d-807f-5011d180c073.pdf</Dateiname> + </Primaerdokument> + </Format> + </Version> + </Dokument> + </Hauptobjekt> + <ExternerGeschaeftsgang> + <Identifikation> + <ID>3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714</ID> + </Identifikation> + <Beteiligungsschritt> + <Nummer>1</Nummer> + <Status listURI="urn:xoev-de:xdomea:codeliste:beteiligungsstatus" listVersionID="1.0"> + <code xmlns="">001</code> + <name xmlns="">Der Schritt liegt in der Zukunft.</name> + </Status> + <Verfuegung> + <Ersteller> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">010200200000</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gad</code> + </Praefix> + </Behoerdenkennung> + </Ersteller> + <Adressat> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">dev-environment@ozg-cloud.de</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gae</code> + </Praefix> + </Behoerdenkennung> + </Adressat> + <Erstellungsdatum>2024-04-24</Erstellungsdatum> + <Erstellungsuhrzeit>16:32:54</Erstellungsuhrzeit> + </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="">019</code> + <name xmlns="">png-Portable Network Graphics</name> + </Name> + <Version>0.0</Version> + <Primaerdokument> + <Dateiname>1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png</Dateiname> + </Primaerdokument> + </Format> + </Version> + </Dokument> + </Anlage> +</Geschaeftsgang.Geschaeftsgang.0201> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml new file mode 100644 index 0000000000000000000000000000000000000000..618c4813e1803a0619c68920505c9ee7cb303b12 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.dataport.de/dFAD/ApplicationDataMessageSchema"> + <ApplicationFormId>08db3c1c-db1f-4d27-8dec-73af167e87f2</ApplicationFormId> + <Timestamp>2023-04-18T11:40:24.9940624+02:00</Timestamp> + <ApplicationDataMessageVersion>1</ApplicationDataMessageVersion> + <Title>Testantrag XML-Fachnachricht-Erweiterung</Title> + <ProjectName>XML-Fachnachricht-Erweiterung</ProjectName> + <ProjectTitle>XML-Fachnachricht-Erweiterung</ProjectTitle> + <TransmittedApplicationId>7AtSMHpx3LfJp4</TransmittedApplicationId> + <InboxReference>sh/sh/4dd01647-b9d9-4775-1b50-08da3d83800a</InboxReference> + <MetaText1>9795669</MetaText1> + <Pages> + <Page> + <Title>Beispiel Seite 1</Title> + <Navigation>Beispiel Seite 1</Navigation> + <Controls> + <Control> + <RadioButtonGroup> + <Label>Beispiel-Steuerelement</Label> + <Alias>beispiel-element</Alias> + <SelectedItems> + <SelectedItem> + <Label>Beispielwert 2</Label> + <Value>bsp-2</Value> + </SelectedItem> + </SelectedItems> + </RadioButtonGroup> + </Control> + </Controls> + </Page> + </Pages> +</application> \ No newline at end of file diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/c2170d27-7a58-4d94-afdf-62c89b9e1557_Zusammenfassung.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/c2170d27-7a58-4d94-afdf-62c89b9e1557_Zusammenfassung.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7b21e652f0decdd019673853696d5ea448f44643 Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/c2170d27-7a58-4d94-afdf-62c89b9e1557_Zusammenfassung.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..023f4e06465e49564310296c91fdc379d9b43a9d --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="utf-8"?> +<Geschaeftsgang.Geschaeftsgang.0201 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:xoev-de:xdomea:schema:2.4.0 xdomea-Nachrichten-VBS.xsd" + xmlns="urn:xoev-de:xdomea:schema:2.4.0"> + <Kopf> + <ProzessID>d5be7468-e620-4126-a40e-61a7f9b46345</ProzessID> + <Nachrichtentyp listURI="urn:xoev-de:xdomea:codeliste:nachrichtentyp" listVersionID="1.0"> + <code xmlns="">0201</code> + </Nachrichtentyp> + <Erstellungszeitpunkt>2023-04-04T06:59:15.4231885+02:00</Erstellungszeitpunkt> + <Absender> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">010100200000</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gad</code> + </Praefix> + </Behoerdenkennung> + </Absender> + <Empfaenger> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">jens.reese@mgm-tp.com</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gae</code> + </Praefix> + </Behoerdenkennung> + </Empfaenger> + <SendendesSystem> + <InstanzID>DE_dFoerdermittelantrag</InstanzID> + <Produktname>dFoerdermittelantrag</Produktname> + <Version>1.0.1.0</Version> + </SendendesSystem> + <EmpfangsbestaetigungAnInitiator>false</EmpfangsbestaetigungAnInitiator> + <EmpfangsbestaetigungAnVorgaenger>false</EmpfangsbestaetigungAnVorgaenger> + </Kopf> + <Hauptobjekt> + <Dokument> + <Identifikation> + <ID>be180ad4-da79-4de2-99b9-86aac2ca7c32</ID> + </Identifikation> + <AllgemeineMetadaten> + <Betreff>OZG-Cloud XTA-Test</Betreff> + <Kennzeichen>08db344b-0302-478e-8bc2-37edeb652460</Kennzeichen> + </AllgemeineMetadaten> + <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>269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml</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>c2170d27-7a58-4d94-afdf-62c89b9e1557_Zusammenfassung.pdf</Dateiname> + </Primaerdokument> + </Format> + </Version> + </Dokument> + </Hauptobjekt> + <ExternerGeschaeftsgang> + <Identifikation> + <ID>269562a3-9142-45b8-9bd2-db840b8322bf</ID> + </Identifikation> + <Beteiligungsschritt> + <Nummer>1</Nummer> + <Status listURI="urn:xoev-de:xdomea:codeliste:beteiligungsstatus" listVersionID="1.0"> + <code xmlns="">001</code> + <name xmlns="">Der Schritt liegt in der Zukunft.</name> + </Status> + <Verfuegung> + <Ersteller> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">010100200000</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gad</code> + </Praefix> + </Behoerdenkennung> + </Ersteller> + <Adressat> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">jens.reese@mgm-tp.com</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gae</code> + </Praefix> + </Behoerdenkennung> + </Adressat> + <Erstellungsdatum>2023-04-04</Erstellungsdatum> + <Erstellungsuhrzeit>06:59:15</Erstellungsuhrzeit> + </Verfuegung> + </Beteiligungsschritt> + </ExternerGeschaeftsgang> +</Geschaeftsgang.Geschaeftsgang.0201> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5b07b65f3a5355f3dc096a260129c5e9aaa0881e Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec0d7a08d0be142997505dd5b6d13015054d5d5 Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d7032ca91a377658636d62a14f0c64f06bf9151 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml @@ -0,0 +1,229 @@ +<?xml version="1.0" encoding="UTF-8"?> +<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" + t:uuid="1d4a1b9b-b456-4d76-becb-eff301665993" t:id="20240404370530710707" t:timestamp="2024-04-04T08:17:33.211Z" + t:sender="test.afm.schleswig-holstein.de" + t:form="Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe" + t:form-id="maa_mantelantrag/maa_mantelantrag" t:customer="Schleswig-Holstein" t:customer-id="sh" + t:client="Schleswig-Holstein" t:client-id="land" t:lang="de" t:vollstaendigkeit="true"> + <gebiets_id>9007404</gebiets_id> + <egh_sgb9>true</egh_sgb9> + <bes_wohnform>false</bes_wohnform> + <hzl>false</hzl> + <grusi>false</grusi> + <hzg>false</hzg> + <hzp>false</hzp> + <hzuebss>false</hzuebss> + <hial>false</hial> + <ambulant>false</ambulant> + <stationaer>false</stationaer> + <sessionid>4cb66bdd-ad27-41c6-8f4b-fc7f023970ad</sessionid> + <anliegen_id>[8969232]</anliegen_id> + <anliegen_namen>[Eingliederungshilfe]</anliegen_namen> + <TypenIDLN>233034601</TypenIDLN> + <logopath1>https://include-sh-schul.zfinder.de/IWFileLoader?tsaid_mediaUUID=21734555-12d6-47aa-bd2e-5794634c592c + </logopath1> + <logopath2/> + <logopath3/> + <gebiet_typid>300004</gebiet_typid> + <gebiet_parent_id1>9006398</gebiet_parent_id1> + <gebiet_parent_typid1>300003</gebiet_parent_typid1> + <gebiet_parent_id2>9006398</gebiet_parent_id2> + <gebiet_parent_typid2>300003</gebiet_parent_typid2> + <gebiet_parent_id3>9006398</gebiet_parent_id3> + <gebiet_parent_typid3>300003</gebiet_parent_typid3> + <gebiet_parent_name3>Segeberg</gebiet_parent_name3> + <oeid>[266237176]</oeid> + <link_datenschutz>https://dse.segeberg.de/pdf/50_30_001.pdf</link_datenschutz> + <link_datenschutz2/> + <link_datenschutz3/> + <link_bankgeheimnis> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_Befreiung_vom_Bankgeheimnis.pdf + </link_bankgeheimnis> + <link_grundsicherung> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Erklaerung_zur_Zahlung_von_Grundsicherungsleistungen_an_Leistungserbringer.pdf + </link_grundsicherung> + <link_schweigepflicht> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Schweigepflichtentbindung.pdf + </link_schweigepflicht> + <link_abtretung> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Einverstaendniserklaerung_und_Abtretung.pdf + </link_abtretung> + <link_wahrheit> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_der_antragstellenden_Person.pdf + </link_wahrheit> + <kontaktsystem_oeid>9795669</kontaktsystem_oeid> + <OrganisationseinheitenBEZEICHNUNG>Kreis Segeberg - Eingliederungshilfe für Minderjährige + </OrganisationseinheitenBEZEICHNUNG> + <zust_strasse>Hamburger Straße</zust_strasse> + <zust_hausnummer>30</zust_hausnummer> + <zust_postleitzahl>23795</zust_postleitzahl> + <ortid>9007404</ortid> + <zust_ort>Bad Segeberg</zust_ort> + <zust_telefonnummer/> + <zust_faxnummer/> + <zust_emailadresse>Eingliederungshilfe-Minderjaehrige@segeberg.de</zust_emailadresse> + <zustellung_nachrichtenbroker>afmsh:010600000000_Online-Dienste</zustellung_nachrichtenbroker> + <zustellung_email_ln/> + <zustellung_webservice/> + <kontaktsystem_oeid2/> + <OrganisationseinheitenBEZEICHNUNG2/> + <zust_strasse2/> + <zust_hausnummer2/> + <zust_postleitzahl2/> + <ortid2/> + <zust_ort2/> + <zust_telefonnummer2/> + <zust_faxnummer2/> + <zust_emailadresse2/> + <zustellung_nachrichtenbroker2/> + <zustellung_email_ln2/> + <zustellung_webservice2/> + <kontaktsystem_oeid3/> + <OrganisationseinheitenBEZEICHNUNG3/> + <zust_strasse3/> + <zust_hausnummer3/> + <zust_postleitzahl3/> + <ortid3/> + <zust_ort3/> + <zust_telefonnummer3/> + <zust_faxnummer3/> + <zust_emailadresse3/> + <zustellung_nachrichtenbroker3/> + <zustellung_email_ln3/> + <zustellung_webservice3/> + <grund>Hilfe</grund> + <a_grund_bescheinigung>false</a_grund_bescheinigung> + <nur_egh>true</nur_egh> + <nur_blindenhilfe>false</nur_blindenhilfe> + <nur_pers_angaben>false</nur_pers_angaben> + <nur_pers_mehrbedarfe>false</nur_pers_mehrbedarfe> + <antragsteller> + <anrede/> + <titel/> + <pers_nachname>Mustermann</pers_nachname> + <geburtsname/> + <pers_vorname>Max</pers_vorname> + <geburtsdatum>2000-04-05</geburtsdatum> + <geburtsort/> + <sh_strasse>Musterstrasse</sh_strasse> + <sh_hausnummer>12</sh_hausnummer> + <adresszusatz/> + <sh_plz>12345</sh_plz> + <ort>Bad Segeberg</ort> + <kont_email/> + <telefon/> + <mobiltelefon/> + <familienstand>ledig</familienstand> + <deutsch>deutsch</deutsch> + <a_ausweisdokument>false</a_ausweisdokument> + <erwerb/> + <erwerbsunfaehig/> + <betreuer>false</betreuer> + <partner>false</partner> + <kont_telefonnummer/> + </antragsteller> + <angaben_antragsteller> + <sozialhilfe_p>Nein</sozialhilfe_p> + <eingliederungshilfe>Nein</eingliederungshilfe> + <leistungen>Nein</leistungen> + <rentenantrag>Nein</rentenantrag> + <sozialversicherungsnummer/> + <rentenbeitraege/> + <auslandserwerb/> + <lebensunterhalt>Arbeit</lebensunterhalt> + <zuzug>false</zuzug> + <pflege_noetig/> + <ansprueche_dritte>false</ansprueche_dritte> + <stoerung_vorhanden>false</stoerung_vorhanden> + <sozialhilfe>Nein</sozialhilfe> + </angaben_antragsteller> + <weitere_personen>false</weitere_personen> + <fin_antragsteller> + <groesse_wohnung unit="m2"/> + <untervermietet_wohnung unit="m2"/> + <raeume/> + <baujahr/> + <wohnung_kosten unit="Euro"/> + <betriebskosten unit="Euro"/> + <heizkosten unit="Euro"/> + <heizart/> + <a_mietvertrag>false</a_mietvertrag> + <pauschalmiete unit="Euro"/> + <warmwasser/> + <miete_vermieter/> + <wohngeld/> + </fin_antragsteller> + <wohnart>Mietwohnung</wohnart> + <ver> + <ver-item> + <name_id>a</name_id> + <versicherung_vorhanden>false</versicherung_vorhanden> + <name>Max Mustermann</name> + <fruehere_kv_vorhanden/> + <frueherer_erwerb_v/> + <bedarf_hzg/> + <kuenftige_kv/> + </ver-item> + </ver> + <werkstatt/> + <leistungen_bezogen>false</leistungen_bezogen> + <einkommen_antragsteller> + <lgh_hzl_bg/> + <nselbststaendig_vorhanden>false</nselbststaendig_vorhanden> + <gewerbe_vorhanden>false</gewerbe_vorhanden> + <landwirtschaft_vorhanden>false</landwirtschaft_vorhanden> + <vermietung_vorhanden>false</vermietung_vorhanden> + <kapital_vorhanden>false</kapital_vorhanden> + <krankenkasse_vorhanden>false</krankenkasse_vorhanden> + <pflegekasse_vorhanden>false</pflegekasse_vorhanden> + <alg_vorhanden>false</alg_vorhanden> + <leistungen_afa_vorhanden>false</leistungen_afa_vorhanden> + <wohngeld_vorhanden>false</wohngeld_vorhanden> + <kindergeld_vorhanden>false</kindergeld_vorhanden> + <elterngeld_vorhanden>false</elterngeld_vorhanden> + <rente_inland_vorhanden>false</rente_inland_vorhanden> + <rente_ausland_vorhanden>false</rente_ausland_vorhanden> + <rente_sonstige_vorhanden>false</rente_sonstige_vorhanden> + <unterhalt_vorhanden>false</unterhalt_vorhanden> + <blindengeld_vorhanden>false</blindengeld_vorhanden> + <sonstiges_vorhanden>false</sonstiges_vorhanden> + <einkommen_gepfaendet>false</einkommen_gepfaendet> + <einkommen_vorhanden>false</einkommen_vorhanden> + </einkommen_antragsteller> + <vermoegen> + <vermoegen-item> + <name_id>a</name_id> + <bargeld_vorhanden>false</bargeld_vorhanden> + <konto_vorhanden>false</konto_vorhanden> + <sparguthaben_vorhanden>false</sparguthaben_vorhanden> + <altersvorsorge_vorhanden>false</altersvorsorge_vorhanden> + <bausparvertraege_vorhanden>false</bausparvertraege_vorhanden> + <aktien_vorhanden>false</aktien_vorhanden> + <paypal_vorhanden>false</paypal_vorhanden> + <lebensversicherung_vorhanden>false</lebensversicherung_vorhanden> + <kfz_vorhanden>false</kfz_vorhanden> + <sachwerte_vorhanden>false</sachwerte_vorhanden> + <haus_vorhanden>false</haus_vorhanden> + <hypotheken_vorhanden>false</hypotheken_vorhanden> + <erbschaft_vorhanden>false</erbschaft_vorhanden> + <sonstiges_vorhanden>false</sonstiges_vorhanden> + <veraeusserung_vermoegen>false</veraeusserung_vermoegen> + <vermoegen_vorhanden>false</vermoegen_vorhanden> + <name>Max Mustermann</name> + </vermoegen-item> + </vermoegen> + <datenerhebung>true</datenerhebung> + <vollstaendigkeit>true</vollstaendigkeit> + <a_befreiung_bankgeheimnis>false</a_befreiung_bankgeheimnis> + <a_entbindung_schweigepflicht>false</a_entbindung_schweigepflicht> + <name_bank/> + <iban/> + <kontoinhaber/> + <name_pdf>Antrag_Max_Mustermann_SGBIX</name_pdf> + <postfachnachicht>Sehr geehrte/r Antragsteller*in,<br/><br/>Ihr Antrag wurde erfolgreich übermittelt.<br/><br/>Bitte + denken Sie daran, zur Vervollständigung Ihres Antrages die unterschriebenen Dokumente und erforderlichen + Nachweise einzureichen.<br/><br/>Die Bearbeitung Ihres Antrages ist erst nach Vorlage aller + erforderlichen Dokumente und Nachweise möglich.<br/><br/><br/>Mit freundlichen Grüßen<br/><br/>Kreis + Segeberg - Eingliederungshilfe für Minderjährige<br/>Hamburger Straße 30<br/>23795 Bad Segeberg + </postfachnachicht> +</myForm> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..add2a33b3c40f57a558fc497e288a42d45c6648f --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,123 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" + codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" + languageCode="de" codelistName="Nachrichtentyp">0201 + </xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-04-04T10:24:07.468+02:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Schleswig-Holstein</xdomea:Name> + <xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>9bae73b1-2ef3-480b-8acc-8bcd9979a788</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe</xdomea:Betreff> + <xdomea:Kennzeichen>20240404370530710707</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-04-04</xdomea:Posteingangsdatum> + <xdomea:Typ>maa_mantelantrag/maa_mantelantrag</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml + </xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + <xdomea:Version> + <xdomea:Nummer>0.0</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>03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf + </xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>8ae49342-8135-4f11-9930-5c4cc55b7ec2</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" + codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001 + </xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-04-04</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>10:24:06</xdomea:Erstellungsuhrzeit> + </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 listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" + xsi:type="DateiformatCodeType"> + <xdomea:code xmlns="">019</xdomea:code> + <xdomea:name xmlns="">png-Portable Network Graphics</xdomea:name> + </xdomea:Name> + <xdomea:Version>0.0</xdomea:Version> + <xdomea:Primaerdokument> + <xdomea:Dateiname>1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Anlage> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5b07b65f3a5355f3dc096a260129c5e9aaa0881e Binary files /dev/null and b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf differ diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d7032ca91a377658636d62a14f0c64f06bf9151 --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml @@ -0,0 +1,229 @@ +<?xml version="1.0" encoding="UTF-8"?> +<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" + t:uuid="1d4a1b9b-b456-4d76-becb-eff301665993" t:id="20240404370530710707" t:timestamp="2024-04-04T08:17:33.211Z" + t:sender="test.afm.schleswig-holstein.de" + t:form="Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe" + t:form-id="maa_mantelantrag/maa_mantelantrag" t:customer="Schleswig-Holstein" t:customer-id="sh" + t:client="Schleswig-Holstein" t:client-id="land" t:lang="de" t:vollstaendigkeit="true"> + <gebiets_id>9007404</gebiets_id> + <egh_sgb9>true</egh_sgb9> + <bes_wohnform>false</bes_wohnform> + <hzl>false</hzl> + <grusi>false</grusi> + <hzg>false</hzg> + <hzp>false</hzp> + <hzuebss>false</hzuebss> + <hial>false</hial> + <ambulant>false</ambulant> + <stationaer>false</stationaer> + <sessionid>4cb66bdd-ad27-41c6-8f4b-fc7f023970ad</sessionid> + <anliegen_id>[8969232]</anliegen_id> + <anliegen_namen>[Eingliederungshilfe]</anliegen_namen> + <TypenIDLN>233034601</TypenIDLN> + <logopath1>https://include-sh-schul.zfinder.de/IWFileLoader?tsaid_mediaUUID=21734555-12d6-47aa-bd2e-5794634c592c + </logopath1> + <logopath2/> + <logopath3/> + <gebiet_typid>300004</gebiet_typid> + <gebiet_parent_id1>9006398</gebiet_parent_id1> + <gebiet_parent_typid1>300003</gebiet_parent_typid1> + <gebiet_parent_id2>9006398</gebiet_parent_id2> + <gebiet_parent_typid2>300003</gebiet_parent_typid2> + <gebiet_parent_id3>9006398</gebiet_parent_id3> + <gebiet_parent_typid3>300003</gebiet_parent_typid3> + <gebiet_parent_name3>Segeberg</gebiet_parent_name3> + <oeid>[266237176]</oeid> + <link_datenschutz>https://dse.segeberg.de/pdf/50_30_001.pdf</link_datenschutz> + <link_datenschutz2/> + <link_datenschutz3/> + <link_bankgeheimnis> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_Befreiung_vom_Bankgeheimnis.pdf + </link_bankgeheimnis> + <link_grundsicherung> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Erklaerung_zur_Zahlung_von_Grundsicherungsleistungen_an_Leistungserbringer.pdf + </link_grundsicherung> + <link_schweigepflicht> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Schweigepflichtentbindung.pdf + </link_schweigepflicht> + <link_abtretung> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Einverstaendniserklaerung_und_Abtretung.pdf + </link_abtretung> + <link_wahrheit> + https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_der_antragstellenden_Person.pdf + </link_wahrheit> + <kontaktsystem_oeid>9795669</kontaktsystem_oeid> + <OrganisationseinheitenBEZEICHNUNG>Kreis Segeberg - Eingliederungshilfe für Minderjährige + </OrganisationseinheitenBEZEICHNUNG> + <zust_strasse>Hamburger Straße</zust_strasse> + <zust_hausnummer>30</zust_hausnummer> + <zust_postleitzahl>23795</zust_postleitzahl> + <ortid>9007404</ortid> + <zust_ort>Bad Segeberg</zust_ort> + <zust_telefonnummer/> + <zust_faxnummer/> + <zust_emailadresse>Eingliederungshilfe-Minderjaehrige@segeberg.de</zust_emailadresse> + <zustellung_nachrichtenbroker>afmsh:010600000000_Online-Dienste</zustellung_nachrichtenbroker> + <zustellung_email_ln/> + <zustellung_webservice/> + <kontaktsystem_oeid2/> + <OrganisationseinheitenBEZEICHNUNG2/> + <zust_strasse2/> + <zust_hausnummer2/> + <zust_postleitzahl2/> + <ortid2/> + <zust_ort2/> + <zust_telefonnummer2/> + <zust_faxnummer2/> + <zust_emailadresse2/> + <zustellung_nachrichtenbroker2/> + <zustellung_email_ln2/> + <zustellung_webservice2/> + <kontaktsystem_oeid3/> + <OrganisationseinheitenBEZEICHNUNG3/> + <zust_strasse3/> + <zust_hausnummer3/> + <zust_postleitzahl3/> + <ortid3/> + <zust_ort3/> + <zust_telefonnummer3/> + <zust_faxnummer3/> + <zust_emailadresse3/> + <zustellung_nachrichtenbroker3/> + <zustellung_email_ln3/> + <zustellung_webservice3/> + <grund>Hilfe</grund> + <a_grund_bescheinigung>false</a_grund_bescheinigung> + <nur_egh>true</nur_egh> + <nur_blindenhilfe>false</nur_blindenhilfe> + <nur_pers_angaben>false</nur_pers_angaben> + <nur_pers_mehrbedarfe>false</nur_pers_mehrbedarfe> + <antragsteller> + <anrede/> + <titel/> + <pers_nachname>Mustermann</pers_nachname> + <geburtsname/> + <pers_vorname>Max</pers_vorname> + <geburtsdatum>2000-04-05</geburtsdatum> + <geburtsort/> + <sh_strasse>Musterstrasse</sh_strasse> + <sh_hausnummer>12</sh_hausnummer> + <adresszusatz/> + <sh_plz>12345</sh_plz> + <ort>Bad Segeberg</ort> + <kont_email/> + <telefon/> + <mobiltelefon/> + <familienstand>ledig</familienstand> + <deutsch>deutsch</deutsch> + <a_ausweisdokument>false</a_ausweisdokument> + <erwerb/> + <erwerbsunfaehig/> + <betreuer>false</betreuer> + <partner>false</partner> + <kont_telefonnummer/> + </antragsteller> + <angaben_antragsteller> + <sozialhilfe_p>Nein</sozialhilfe_p> + <eingliederungshilfe>Nein</eingliederungshilfe> + <leistungen>Nein</leistungen> + <rentenantrag>Nein</rentenantrag> + <sozialversicherungsnummer/> + <rentenbeitraege/> + <auslandserwerb/> + <lebensunterhalt>Arbeit</lebensunterhalt> + <zuzug>false</zuzug> + <pflege_noetig/> + <ansprueche_dritte>false</ansprueche_dritte> + <stoerung_vorhanden>false</stoerung_vorhanden> + <sozialhilfe>Nein</sozialhilfe> + </angaben_antragsteller> + <weitere_personen>false</weitere_personen> + <fin_antragsteller> + <groesse_wohnung unit="m2"/> + <untervermietet_wohnung unit="m2"/> + <raeume/> + <baujahr/> + <wohnung_kosten unit="Euro"/> + <betriebskosten unit="Euro"/> + <heizkosten unit="Euro"/> + <heizart/> + <a_mietvertrag>false</a_mietvertrag> + <pauschalmiete unit="Euro"/> + <warmwasser/> + <miete_vermieter/> + <wohngeld/> + </fin_antragsteller> + <wohnart>Mietwohnung</wohnart> + <ver> + <ver-item> + <name_id>a</name_id> + <versicherung_vorhanden>false</versicherung_vorhanden> + <name>Max Mustermann</name> + <fruehere_kv_vorhanden/> + <frueherer_erwerb_v/> + <bedarf_hzg/> + <kuenftige_kv/> + </ver-item> + </ver> + <werkstatt/> + <leistungen_bezogen>false</leistungen_bezogen> + <einkommen_antragsteller> + <lgh_hzl_bg/> + <nselbststaendig_vorhanden>false</nselbststaendig_vorhanden> + <gewerbe_vorhanden>false</gewerbe_vorhanden> + <landwirtschaft_vorhanden>false</landwirtschaft_vorhanden> + <vermietung_vorhanden>false</vermietung_vorhanden> + <kapital_vorhanden>false</kapital_vorhanden> + <krankenkasse_vorhanden>false</krankenkasse_vorhanden> + <pflegekasse_vorhanden>false</pflegekasse_vorhanden> + <alg_vorhanden>false</alg_vorhanden> + <leistungen_afa_vorhanden>false</leistungen_afa_vorhanden> + <wohngeld_vorhanden>false</wohngeld_vorhanden> + <kindergeld_vorhanden>false</kindergeld_vorhanden> + <elterngeld_vorhanden>false</elterngeld_vorhanden> + <rente_inland_vorhanden>false</rente_inland_vorhanden> + <rente_ausland_vorhanden>false</rente_ausland_vorhanden> + <rente_sonstige_vorhanden>false</rente_sonstige_vorhanden> + <unterhalt_vorhanden>false</unterhalt_vorhanden> + <blindengeld_vorhanden>false</blindengeld_vorhanden> + <sonstiges_vorhanden>false</sonstiges_vorhanden> + <einkommen_gepfaendet>false</einkommen_gepfaendet> + <einkommen_vorhanden>false</einkommen_vorhanden> + </einkommen_antragsteller> + <vermoegen> + <vermoegen-item> + <name_id>a</name_id> + <bargeld_vorhanden>false</bargeld_vorhanden> + <konto_vorhanden>false</konto_vorhanden> + <sparguthaben_vorhanden>false</sparguthaben_vorhanden> + <altersvorsorge_vorhanden>false</altersvorsorge_vorhanden> + <bausparvertraege_vorhanden>false</bausparvertraege_vorhanden> + <aktien_vorhanden>false</aktien_vorhanden> + <paypal_vorhanden>false</paypal_vorhanden> + <lebensversicherung_vorhanden>false</lebensversicherung_vorhanden> + <kfz_vorhanden>false</kfz_vorhanden> + <sachwerte_vorhanden>false</sachwerte_vorhanden> + <haus_vorhanden>false</haus_vorhanden> + <hypotheken_vorhanden>false</hypotheken_vorhanden> + <erbschaft_vorhanden>false</erbschaft_vorhanden> + <sonstiges_vorhanden>false</sonstiges_vorhanden> + <veraeusserung_vermoegen>false</veraeusserung_vermoegen> + <vermoegen_vorhanden>false</vermoegen_vorhanden> + <name>Max Mustermann</name> + </vermoegen-item> + </vermoegen> + <datenerhebung>true</datenerhebung> + <vollstaendigkeit>true</vollstaendigkeit> + <a_befreiung_bankgeheimnis>false</a_befreiung_bankgeheimnis> + <a_entbindung_schweigepflicht>false</a_entbindung_schweigepflicht> + <name_bank/> + <iban/> + <kontoinhaber/> + <name_pdf>Antrag_Max_Mustermann_SGBIX</name_pdf> + <postfachnachicht>Sehr geehrte/r Antragsteller*in,<br/><br/>Ihr Antrag wurde erfolgreich übermittelt.<br/><br/>Bitte + denken Sie daran, zur Vervollständigung Ihres Antrages die unterschriebenen Dokumente und erforderlichen + Nachweise einzureichen.<br/><br/>Die Bearbeitung Ihres Antrages ist erst nach Vorlage aller + erforderlichen Dokumente und Nachweise möglich.<br/><br/><br/>Mit freundlichen Grüßen<br/><br/>Kreis + Segeberg - Eingliederungshilfe für Minderjährige<br/>Hamburger Straße 30<br/>23795 Bad Segeberg + </postfachnachicht> +</myForm> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f742978a9470f48f962da1fa169c0090b8448fe --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,101 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" + codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" + languageCode="de" codelistName="Nachrichtentyp">0201 + </xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-04-04T10:24:07.468+02:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Schleswig-Holstein</xdomea:Name> + <xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>9bae73b1-2ef3-480b-8acc-8bcd9979a788</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe</xdomea:Betreff> + <xdomea:Kennzeichen>20240404370530710707</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-04-04</xdomea:Posteingangsdatum> + <xdomea:Typ>maa_mantelantrag/maa_mantelantrag</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml + </xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + <xdomea:Version> + <xdomea:Nummer>0.0</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>03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf + </xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>8ae49342-8135-4f11-9930-5c4cc55b7ec2</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" + codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001 + </xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-04-04</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>10:24:06</xdomea:Erstellungsuhrzeit> + </xdomea:Verfuegung> + </xdomea:Beteiligungsschritt> + </xdomea:ExternerGeschaeftsgang> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201> \ No newline at end of file diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml new file mode 100644 index 0000000000000000000000000000000000000000..4dabcc067d040ad07fda5101e4c6527459b5d53d --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<myForm xmlns:pdf="http://xmlns.cit.de/assistants/pdf" xmlns:t="http://xmlns.cit.de/intelliform/transaction" t:uuid="2b1b5768-e9b4-47f6-859e-c197ef4361a3" t:id="20240321325940124004" t:timestamp="2024-03-21T08:03:14.724Z" t:sender="test.afm.schleswig-holstein.de" t:form="Kleiner Waffenschein NB Test" t:form-id="waffen/kleinerWaffenscheinNB" t:customer="Einheitlicher Ansprechpartner" t:customer-id="ea-sh" t:client="Schleswig-Holstein" t:client-id="land" t:lang="de"> + <KontaktsystemTypA>233034600</KontaktsystemTypA> + <KontaktsystemTypB>233034601</KontaktsystemTypB> + <AnliegenID>8966671</AnliegenID> + <antragsteller> + <pers_anrede>Herr$03</pers_anrede> + <pers_nachname>Max</pers_nachname> + <pers_vorname>Mustermann</pers_vorname> + <pers_geburtsname>Mustermann</pers_geburtsname> + <pers_geburtsdatum>2000-02-15</pers_geburtsdatum> + <pers_geburtsort>Eutin</pers_geburtsort> + <pers_geburtsland>deutsch$Deutschland$000</pers_geburtsland> + <pers_staatsangehoerigkeit>deutsch$Deutschland$000</pers_staatsangehoerigkeit> + <b_anrede>Herr</b_anrede> + <b_anrede_schluesselnr>03</b_anrede_schluesselnr> + <b_geburtsland>Deutschland</b_geburtsland> + <b_geburtsland_signatur>000</b_geburtsland_signatur> + <b_staatsangehoerigkeit>deutsch</b_staatsangehoerigkeit> + <b_staatsangehoerigkeit_signatur>000</b_staatsangehoerigkeit_signatur> + <sh_strasse>Musterstrasse</sh_strasse> + <sh_hausnummer>123</sh_hausnummer> + <sh_plz>23701</sh_plz> + <ort_auswahl>9006885$01055012</ort_auswahl> + <ort>Eutin</ort> + <GebietID>9006885</GebietID> + <GebietBEZEICHNUNG>Eutin</GebietBEZEICHNUNG> + <GebietGNR94_GNR>01055012</GebietGNR94_GNR> + <staat>000</staat> + <iso3166numerisch>276</iso3166numerisch> + <kont_telefonnummer /> + <kont_mobilnummer /> + <kont_telefaxnummer /> + <kont_email /> + <kont_demail /> + <persoenlicheEignung> + <maengelvorhanden>false</maengelvorhanden> + <ermittlungsverfahren>false</ermittlungsverfahren> + <MitgliedschaftInVerboternerVereinigung>false</MitgliedschaftInVerboternerVereinigung> + </persoenlicheEignung> + </antragsteller> + <GebietID>9006885</GebietID> + <zustaendigestelle> + <OrganisationseinheitenAuswahl>279550874</OrganisationseinheitenAuswahl> + <OrganisationseinheitenID>9795669</OrganisationseinheitenID> + <OrganisationseinheitenBEZEICHNUNG>Fachdienst Sicherheit und Ordnung - Kreis Ostholstein</OrganisationseinheitenBEZEICHNUNG> + <strasse>Lübecker Straße</strasse> + <hausnummer>41</hausnummer> + <postleitzahl>23701</postleitzahl> + <ortID>9006885</ortID> + <ort>Eutin</ort> + <telefonnummer>+49 4521 788-0</telefonnummer> + <telefaxnummer>+49 4521 788-292</telefaxnummer> + <emailadresse>sicherheit@kreis-oh.de</emailadresse> + <demailadresse /> + <kontaktsystem_kennung /> + <kontaktsystem_kennungzusatz /> + <AnliegenBEZEICHNUNG>Waffenschein beantragen</AnliegenBEZEICHNUNG> + <leikaKEYLIST>99089122001000</leikaKEYLIST> + <auswahl_zustellung>abholen</auswahl_zustellung> + <b_zustellung>Ich hole den Kleinen Waffenschein selbst ab.</b_zustellung> + </zustaendigestelle> + <empfangendestelle> + <OrganisationseinheitenAuswahl>9068873</OrganisationseinheitenAuswahl> + <OrganisationseinheitenID>9068873</OrganisationseinheitenID> + <OrganisationseinheitenBEZEICHNUNG>Einheitlicher Ansprechpartner Schleswig-Holstein</OrganisationseinheitenBEZEICHNUNG> + <strasse>Deliusstraße</strasse> + <hausnummer>10</hausnummer> + <postleitzahl>24114</postleitzahl> + <ortID>9006402</ortID> + <ort>Kiel</ort> + <telefonnummer>+49 431 530550-0</telefonnummer> + <telefaxnummer>+49 431 530550-99</telefaxnummer> + <emailadresse>info@ea-sh.de</emailadresse> + <demailadresse>ea-poststelle@ea-sh.de-mail.de</demailadresse> + <kontaktsystem_kennung>afmsh:9068873_AusnahmeLKWFahrverbot</kontaktsystem_kennung> + <kontaktsystem_kennungzusatz>alle</kontaktsystem_kennungzusatz> + </empfangendestelle> + <erklaerungen> + <check_gebuehren>true</check_gebuehren> + <check_richtigkeit>true</check_richtigkeit> + <check_datenschutz>true</check_datenschutz> + <check_missbrauch>true</check_missbrauch> + <b_gebuehren_beschriftung>* Mir ist bekannt, dass durch das Einreichen des elektronischen Antrages von der zuständigen Stelle Gebühren erhoben werden können.</b_gebuehren_beschriftung> + <b_gebuehren_intro>Gebühr bei Ausstellung des kleinen Waffenscheins: 60,00 Euro. Bearbeitungsgebühr bei Versagung: 45,00 Euro. + Sie sind gemäß § 39 WaffG verpflichtet, der zuständigen Behörde die zur Durchführung des Gesetzes erforderlichen Auskünfte zu erteilen. Zur Prüfung Ihrer waffenrechtlichen Zuverlässigkeit und Eignung holt die Behörde eine unbeschränkte Auskunft aus dem Bundeszentralregister, eine Auskunft aus dem zentralen staatsanwaltschaftlichen Verfahrensregister, eine Stellungnahme der örtlichen Polizeidienststelle und Ihrer Wohnsitzgemeinde ein.</b_gebuehren_intro> + <b_richtigkeit>* Ich bestätige die Richtigkeit meiner Angaben.</b_richtigkeit> + <b_datenschutz>* Ich erkläre mich damit einverstanden, dass der Einheitlicher Ansprechpartner Schleswig-Holstein zur Erfüllung seiner Aufgaben meine Daten unter Einhaltung der Bestimmungen der Datenschutz-Grundverordnung (DS-GVO) und des Landesdatenschutzgesetzes Schleswig-Holstein (LDSG-SH) speichert, verarbeitet und diese im Rahmen der gesetzlichen Bestimmungen an die für die Entscheidung zuständige Stelle weiterleitet. Ebenso bin ich mit der rechtskonformen Datenverarbeitung und Speicherung durch die zuständige Stelle einverstanden. Mir ist bekannt, dass ich die Einwilligung in die Verarbeitung und Übermittlung jederzeit gegenüber dem Einheitlicher Ansprechpartner Schleswig-Holstein, Deliusstraße 10, 24114 Kiel widerrufen kann. Ein Widerruf ist aber nur wirksam für die Zukunft. Verarbeitungen, die vor dem Widerruf erfolgt sind, sind davon nicht betroffen. Über die Verarbeitung meiner personenbezogenen Daten und die mir nach den datenschutzrechtlichen Regelungen zustehenden Ansprüche und Rechte habe ich unter Datenschutzerklärung Kenntnis erlangt.</b_datenschutz> + <b_missbrauch>* Mir ist bekannt, dass zur Verfolgung widerrechtlicher Nutzung die Daten meines zur Dateneingabe genutzten Endgerätes aufgezeichnet und verwendet werden können.</b_missbrauch> + <policyurl>http://www.ea-sh.info/datenschutz/datenschutzerklaerungEA_de.doc</policyurl> + </erklaerungen> + <logourl>http://www.ea-sh.info/logos/kopf_9068873.doc</logourl> + <fm> + <ansprechpartner> + <firmenname /> + <anrede>Herr</anrede> + <vorname>Mustermann</vorname> + <familienname>Max</familienname> + <anschrift> + <strasse>Musterstrasse</strasse> + <hausnummer>123</hausnummer> + <postfach /> + <postleitzahl>23701</postleitzahl> + <ort>Eutin</ort> + <ortsteil /> + <zusatz /> + <staat>Deutschland</staat> + </anschrift> + <kontakt> + <telefonnummer /> + <mobilnummer /> + <telefaxnummer /> + <emailadresse /> + <demailadresse /> + </kontakt> + </ansprechpartner> + <verwaltungsleistungen> + <verwaltungsleistung> + <ausgewaehlte_zustaendigestelle> + <OrganisationseinheitenID>279550874</OrganisationseinheitenID> + <OrganisationseinheitenBEZEICHNUNG>Fachdienst Sicherheit und Ordnung - Kreis Ostholstein</OrganisationseinheitenBEZEICHNUNG> + </ausgewaehlte_zustaendigestelle> + <GebietID>9006885</GebietID> + <GebietBEZEICHNUNG>Eutin</GebietBEZEICHNUNG> + <AnliegenID>8966671</AnliegenID> + <AnliegenBEZEICHNUNG>Waffenschein beantragen</AnliegenBEZEICHNUNG> + <leikaKEYLIST>99089122001000</leikaKEYLIST> + <leikaBEZEICHNUNG /> + </verwaltungsleistung> + </verwaltungsleistungen> + </fm> +</myForm> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/d254806f-abf4-4e4c-ae74-ea03460f34d2_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/d254806f-abf4-4e4c-ae74-ea03460f34d2_Geschaeftsgang.Geschaeftsgang.0201.xml new file mode 100644 index 0000000000000000000000000000000000000000..1eaa092e8b3c7f63a6cdf276f3ef763a1302274d --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/d254806f-abf4-4e4c-ae74-ea03460f34d2_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,79 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>d254806f-abf4-4e4c-ae74-ea03460f34d2</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Nachrichtentyp">0201</xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-03-21T09:05:01.424+01:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Einheitlicher Ansprechpartner</xdomea:Name> + <xdomea:Kurzbezeichnung>Einheitlicher Ansprechpartner</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001 ">ozg-cloud-dev001 </xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>5b4e3f41-180b-4a9f-aa5b-19f9aa72f32e</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Kleiner Waffenschein NB Test</xdomea:Betreff> + <xdomea:Kennzeichen>20240321325940124004</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-03-21</xdomea:Posteingangsdatum> + <xdomea:Typ>waffen/kleinerWaffenscheinNB</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>1f6e0806-f9eb-4bb3-88ad-0828411f1f2c</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001</xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001 ">ozg-cloud-dev001 </xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-03-21</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>09:05:01</xdomea:Erstellungsuhrzeit> + </xdomea:Verfuegung> + </xdomea:Beteiligungsschritt> + </xdomea:ExternerGeschaeftsgang> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201> diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/fim.S17000652.17000652001004/versammlungsanzeige.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/fim.S17000652.17000652001004/versammlungsanzeige.xml new file mode 100644 index 0000000000000000000000000000000000000000..e535ee0d452895989e769142c40dd29ee8e4d87e --- /dev/null +++ b/xta-adapter/src/test/resources/mock-responses/getMessage/fim.S17000652.17000652001004/versammlungsanzeige.xml @@ -0,0 +1 @@ +<fim.S17000652.17000652001004 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:xoev-de:xfall:standard:fim-s17000652_1.4"><G17003529><G05001479><G05001480><F05002750>85ad506f-25a2-4a93-a086-b069784c6d60</F05002750><F05002751>21.03.2024 08:56:33</F05002751><F05002752>fim.S17000652.17000652001004</F05002752><F05002753>urn:fim:Versammlungsanzeige:1.4</F05002753></G05001480><G05001481><F05002754>Fachdienst Sicherheit und Ordnung - Kreis Ostholstein</F05002754><F05002755>vbe:010550120100</F05002755><F05002756>Versammlungsbehörde</F05002756></G05001481><G05001482><F05002754>Dataport</F05002754><F05002755>ehp:010100100000</F05002755><F05002756>Versammlungsbehörde</F05002756></G05001482></G05001479><F17005454>true</F17005454><F17005455>false</F17005455><F17005533>85ad506f-25a2-4a93-a086-b069784c6d60</F17005533></G17003529><F17009191>false</F17009191><G17002112><F60000228>Jörg</F60000228><F60000227>Bolay</F60000227><G60000086><F60000243>Muster</F60000243><F60000244>1</F60000244><F60000246>12345</F60000246><F60000247>Muster</F60000247></G60000086><F60000242>joerg.bolay@dataport.de</F60000242><F17009011>false</F17009011></G17002112><F17003371>Anzeigen einer ortsfesten Versammlung (Kundgebung / Demonstration)</F17003371><G17005404><G17007202><F17003373>fsdf</F17003373><F17003377>sdf</F17003377><G17005406><F60000048>2024-03-21</F60000048><F17001348>13.5</F17001348><F60000049>2024-03-21</F60000049><F17001349>15</F17001349></G17005406></G17007202><G17007205><F17003379>10</F17003379><F17003382>keine</F17003382><G17007234><F17011826>Nein</F17011826></G17007234><G17007235><F17011827>Nein</F17011827></G17007235></G17007205></G17005404></fim.S17000652.17000652001004> \ No newline at end of file diff --git a/xta-adapter/src/test/resources/test_content.zip b/xta-adapter/src/test/resources/test_content.zip deleted file mode 100644 index e2c9e434c49cf52a8d0840b1a25dcc52615df04c..0000000000000000000000000000000000000000 Binary files a/xta-adapter/src/test/resources/test_content.zip and /dev/null differ 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 new file mode 100644 index 0000000000000000000000000000000000000000..28200a104f3cb7ded5851105ad2d9fd80034bc3c --- /dev/null +++ b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8"?> +<Geschaeftsgang.Geschaeftsgang.0201 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="urn:xoev-de:xdomea:schema:2.4.0 xdomea-Nachrichten-VBS.xsd" xmlns="urn:xoev-de:xdomea:schema:2.4.0"> + <Kopf> + <ProzessID>b42b7984-279c-4260-8b48-c0389555608c</ProzessID> + <Nachrichtentyp listURI="urn:xoev-de:xdomea:codeliste:nachrichtentyp" listVersionID="1.0"> + <code xmlns="">0201</code> + </Nachrichtentyp> + <Erstellungszeitpunkt>2024-04-22T16:14:18.1885313+02:00</Erstellungszeitpunkt> + <Absender> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">010200200000</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gad</code> + </Praefix> + </Behoerdenkennung> + </Absender> + <Empfaenger> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">dev-environment@ozg-cloud.de</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gae</code> + </Praefix> + </Behoerdenkennung> + </Empfaenger> + <SendendesSystem> + <InstanzID>HH_dFoerdermittelantrag</InstanzID> + <Produktname>dFoerdermittelantrag</Produktname> + <Version>2.1.999.0</Version> + </SendendesSystem> + <EmpfangsbestaetigungAnInitiator>false</EmpfangsbestaetigungAnInitiator> + <EmpfangsbestaetigungAnVorgaenger>false</EmpfangsbestaetigungAnVorgaenger> + </Kopf> + <Hauptobjekt> + <Dokument> + <Identifikation> + <ID>0e7734d8-bf3f-4f8d-9568-3791abf8fe44</ID> + </Identifikation> + <AllgemeineMetadaten> + <Betreff>Testantrag für die OZG-Cloud</Betreff> + <Kennzeichen>08dc497a-f1d4-412d-80ca-4f58405dc83e</Kennzeichen> + </AllgemeineMetadaten> + <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>%s</Dateiname> + </Primaerdokument> + </Format> + </Version> + </Dokument> + </Hauptobjekt> + <ExternerGeschaeftsgang> + <Identifikation> + <ID>78fd7cf4-e9b2-4df1-9dc3-3b192a9d61d3</ID> + </Identifikation> + <Beteiligungsschritt> + <Nummer>1</Nummer> + <Status listURI="urn:xoev-de:xdomea:codeliste:beteiligungsstatus" listVersionID="1.0"> + <code xmlns="">001</code> + <name xmlns="">Der Schritt liegt in der Zukunft.</name> + </Status> + <Verfuegung> + <Ersteller> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">010200200000</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gad</code> + </Praefix> + </Behoerdenkennung> + </Ersteller> + <Adressat> + <Behoerdenkennung> + <Kennung listURI="" listVersionID=""> + <code xmlns="">dev-environment@ozg-cloud.de</code> + </Kennung> + <Praefix listURI="" listVersionID=""> + <code xmlns="">gae</code> + </Praefix> + </Behoerdenkennung> + </Adressat> + <Erstellungsdatum>2024-04-22</Erstellungsdatum> + <Erstellungsuhrzeit>16:14:18</Erstellungsuhrzeit> + </Verfuegung> + </Beteiligungsschritt> + </ExternerGeschaeftsgang> +</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 new file mode 100644 index 0000000000000000000000000000000000000000..349a7a5c3a2406981d48091a319a7aa8f63b16f0 --- /dev/null +++ b/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml @@ -0,0 +1,99 @@ +<?xml version="1.0"?> +<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1"> + <xdomea:Kopf> + <xdomea:ProzessID>9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2</xdomea:ProzessID> + <xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" + codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" + languageCode="de" codelistName="Nachrichtentyp">0201 + </xdomea:Nachrichtentyp> + <xdomea:Erstellungszeitpunkt>2024-04-04T10:24:07.468+02:00</xdomea:Erstellungszeitpunkt> + <xdomea:Absender> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + <xdomea:Institution> + <xdomea:Name>Schleswig-Holstein</xdomea:Name> + <xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung> + </xdomea:Institution> + </xdomea:Absender> + <xdomea:Empfaenger> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Empfaenger> + <xdomea:SendendesSystem> + <xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID> + <xdomea:Produktname>MSR</xdomea:Produktname> + <xdomea:Version>10.5</xdomea:Version> + </xdomea:SendendesSystem> + <xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator> + <xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger> + </xdomea:Kopf> + <xdomea:Hauptobjekt> + <xdomea:Dokument> + <xdomea:Identifikation> + <xdomea:ID>9bae73b1-2ef3-480b-8acc-8bcd9979a788</xdomea:ID> + </xdomea:Identifikation> + <xdomea:AllgemeineMetadaten> + <xdomea:Betreff>Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe</xdomea:Betreff> + <xdomea:Kennzeichen>20240404370530710707</xdomea:Kennzeichen> + </xdomea:AllgemeineMetadaten> + <xdomea:Posteingangsdatum>2024-04-04</xdomea:Posteingangsdatum> + <xdomea:Typ>maa_mantelantrag/maa_mantelantrag</xdomea:Typ> + <xdomea:Version> + <xdomea:Nummer>0.0</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>0.0</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>%s</xdomea:Dateiname> + </xdomea:Primaerdokument> + </xdomea:Format> + </xdomea:Version> + </xdomea:Dokument> + </xdomea:Hauptobjekt> + <xdomea:ExternerGeschaeftsgang> + <xdomea:Identifikation> + <xdomea:ID>8ae49342-8135-4f11-9930-5c4cc55b7ec2</xdomea:ID> + </xdomea:Identifikation> + <xdomea:Beteiligungsschritt> + <xdomea:Nummer>1</xdomea:Nummer> + <xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" + codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001 + </xdomea:Status> + <xdomea:Verfuegung> + <xdomea:Ersteller> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Ersteller> + <xdomea:Adressat> + <xdomea:Behoerdenkennung> + <xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung> + <xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix> + </xdomea:Behoerdenkennung> + </xdomea:Adressat> + <xdomea:Erstellungsdatum>2024-04-04</xdomea:Erstellungsdatum> + <xdomea:Erstellungsuhrzeit>10:24:06</xdomea:Erstellungsuhrzeit> + </xdomea:Verfuegung> + </xdomea:Beteiligungsschritt> + </xdomea:ExternerGeschaeftsgang> +</xdomea:Geschaeftsgang.Geschaeftsgang.0201>