diff --git a/semantik-adapter/pom.xml b/semantik-adapter/pom.xml index a650a35fb75a3bf63d4068cd613558e985304d38..6867cda78180244cd25831eaf31f8060c7d9d5c0 100644 --- a/semantik-adapter/pom.xml +++ b/semantik-adapter/pom.xml @@ -42,6 +42,17 @@ <groupId>de.itvsh.kop.eingangsadapter</groupId> <artifactId>router</artifactId> </dependency> + + <!-- Tools --> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-xml</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + </dependency> <!-- test --> <dependency> diff --git a/semantik-adapter/src/main/java/de/itvsh/kop/eingangsadapter/semantik/formbased/DFoerdermittelFormBasedMapper.java b/semantik-adapter/src/main/java/de/itvsh/kop/eingangsadapter/semantik/formbased/DFoerdermittelFormBasedMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..aba71d524317fb377a881a2b3feb9523cd74a4c6 --- /dev/null +++ b/semantik-adapter/src/main/java/de/itvsh/kop/eingangsadapter/semantik/formbased/DFoerdermittelFormBasedMapper.java @@ -0,0 +1,63 @@ +package de.itvsh.kop.eingangsadapter.semantik.formbased; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; + +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +import de.itvsh.kop.eingangsadapter.common.formdata.FormData; +import de.itvsh.kop.eingangsadapter.common.formdata.IncomingFile; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class DFoerdermittelFormBasedMapper implements FormBasedMapper { + + private static final String FACHNACHRICHT_SUFFIX = "Fachnachricht.xml"; + private static final Predicate<IncomingFile> IS_FACHNACHRICHT = inFile -> StringUtils.endsWith(inFile.getName(), FACHNACHRICHT_SUFFIX); + + private static final String KEY_FACHNACHRICHT = "Fachnachricht"; + + @Override + public FormData parseFormData(FormData formData) { + return formData.getRepresentations().stream().filter(IS_FACHNACHRICHT).findAny() + .map(inFile -> parseFachnachricht(formData, inFile)) + .orElse(formData); + } + + FormData parseFachnachricht(FormData formData, IncomingFile fachnachrichtFile) { + // TODO allow re-reading of incoming file + var fachnachrichtData = extractFormDataFormXML(fachnachrichtFile.getContentStream()); + + if (fachnachrichtData != null) { + var editable = new HashMap<>(formData.getFormData()); + editable.put(KEY_FACHNACHRICHT, fachnachrichtData); + return formData.toBuilder().formData(Collections.unmodifiableMap(editable)).build(); + } + + return formData; + } + + @SuppressWarnings("unchecked") + Map<String, Object> extractFormDataFormXML(InputStream xmlFileStream) { + + XmlMapper xmlMapper = new XmlMapper(); + try { + return xmlMapper.readValue(xmlFileStream, Map.class); + } catch (IOException e) { + LOG.error("Error reading xml fachnachricht.", e); + } + return null; + } + + @Override + public boolean isResponsible(FormData formData) { + return formData.getRepresentations().stream().anyMatch(IS_FACHNACHRICHT); + } + +} diff --git a/semantik-adapter/src/test/java/de/itvsh/kop/eingangsadapter/semantik/formbased/DFoerdermittelFormBasedMapperTest.java b/semantik-adapter/src/test/java/de/itvsh/kop/eingangsadapter/semantik/formbased/DFoerdermittelFormBasedMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fc7eea7f60f121d5d74fde20d4082376117c90cb --- /dev/null +++ b/semantik-adapter/src/test/java/de/itvsh/kop/eingangsadapter/semantik/formbased/DFoerdermittelFormBasedMapperTest.java @@ -0,0 +1,115 @@ +package de.itvsh.kop.eingangsadapter.semantik.formbased; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.Collections; +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.InjectMocks; +import org.mockito.Spy; + +import de.itvsh.kop.common.test.TestUtils; +import de.itvsh.kop.eingangsadapter.common.formdata.FormData; +import de.itvsh.kop.eingangsadapter.common.formdata.FormDataTestFactory; +import de.itvsh.kop.eingangsadapter.common.formdata.IncomingFile; + +class DFoerdermittelFormBasedMapperTest { + + @Spy + @InjectMocks + private DFoerdermittelFormBasedMapper mapper; + + @Nested + class TestIsResponsible { + + @Test + void shouldBeTrueWithFachnachricht() { + var responsible = mapper.isResponsible(createWithFachnachricht()); + + assertThat(responsible).isTrue(); + } + + @Test + void shouldBeFalseForOuther() { + var responsible = mapper.isResponsible(FormDataTestFactory.create()); + + assertThat(responsible).isFalse(); + } + } + + @Nested + class TestParseFachnachricht { + + @Nested + class ExtractData { + @Test + void shouldHaveFormData() { + var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); + + assertThat(result).isNotNull(); + } + + @Test + void shouldHavePages() { + var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); + + assertThat(result).containsKey("Pages"); + } + + @Test + void shouldHaveInboxRef() { + var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")); + + assertThat(result).containsEntry("InboxReference", "sh/sh/4dd01647-b9d9-4775-1b50-08da3d83800a"); + } + } + + @Nested + class HandleFachnachrichtData { + + private Map<String, Object> extracted = Collections.emptyMap(); + + @BeforeEach + void init() { + doReturn(extracted).when(mapper).extractFormDataFormXML(any()); + } + + @Test + void shouldCallExtractData() { + mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); + + verify(mapper).extractFormDataFormXML(notNull()); + } + + @Test + void shouldAddMap() { + + var result = mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile()); + + assertThat(result.getFormData()).containsEntry("Fachnachricht", extracted); + } + } + + } + + FormData createWithFachnachricht() { + + return FormData.builder() + .formData(Collections.emptyMap()) + .representation(createFachnachrichtFile()).build(); + } + + IncomingFile createFachnachrichtFile() { + return IncomingFile.builder() + .contentStream(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml")) + .contentType("application/xml") + .size(1283) + .name("Beispieldatensatz_Fachnachricht.xml") + .build(); + } +} diff --git a/semantik-adapter/src/test/resources/xta/Beispieldatensatz_Fachnachricht.xml b/semantik-adapter/src/test/resources/xta/Beispieldatensatz_Fachnachricht.xml new file mode 100644 index 0000000000000000000000000000000000000000..618c4813e1803a0619c68920505c9ee7cb303b12 --- /dev/null +++ b/semantik-adapter/src/test/resources/xta/Beispieldatensatz_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