diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapper.java index e8ff80f8d833cd1af8d2ab867b4b3ea990fe7c5b..cda9bd6842a89445a7dfc08d376f8d05725a02f7 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapper.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import de.ozgcloud.eingang.common.formdata.FormData; @@ -43,8 +44,14 @@ class AfmZustaendigeStelleMapper implements AfmEngineBasedMapper { public static final String ORGANISATIONSEINHEITEN_ID = "OrganisationseinheitenID"; public static final String TAG_BEZEICHNUNG = "OrganisationseinheitenBEZEICHNUNG"; + @Autowired + private BayernBehoerdeMetadataMapper bayernBehoerdeMetadataMapper; + @Override public FormData parseFormData(FormData formData) { + if (bayernBehoerdeMetadataMapper.isResponsible(formData)) { + return bayernBehoerdeMetadataMapper.parseZustaendigeStelleData(formData); + } var zustaendigeStelleMap = getZustaendigeStelle(formData); var organisationseinheitenID = getOrganisationseinheitenId(formData); var builder = ZustaendigeStelle.builder(); diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernBehoerdeMetadataMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernBehoerdeMetadataMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..7417593b447e01993c7ea22b06f0541ecdc87271 --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernBehoerdeMetadataMapper.java @@ -0,0 +1,77 @@ +package de.ozgcloud.eingang.semantik.enginebased.afm; + +import static java.util.Objects.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Component +public class BayernBehoerdeMetadataMapper { + + static final String BEHOERDE_METADATA_SUFFIX = "behoerde_metadata.xml"; + + private static final Predicate<IncomingFile> IS_BEHOERDE_METADATA = inFile -> StringUtils.endsWith(inFile.getName(), BEHOERDE_METADATA_SUFFIX); + + static final String KEY_BEHOERDE_ANZEIGE_NAME = "behoerde_anzeige_name"; + static final String KEY_BEHOERDE_CALLER_ID = "behoerde_caller_id"; + static final String KEY_GEMEINDE_SCHLUESSEL_BP = "gemeinde_schluessel_bp"; + static final String KEY_BEHOERDE_EMAIL = "behoerde_email"; + static final String KEY_AMTLICHER_REGIONALSCHLUESSEL = "amtlicher_regionalschluessel"; + static final String KEY_BEHOERDE_HAUSANSCHRIFT_STRASSE = "behoerde_hausanschrift_strasse"; + static final String KEY_BEHOERDE_HAUSANSCHRIFT_ORT = "behoerde_hausanschrift_ort"; + static final String KEY_BEHOERDE_HAUSANSCHRIFT_PLZ = "behoerde_hausanschrift_plz"; + static final String KEY_BEHOERDE_TELEFON = "behoerde_telefon"; + + public FormData parseZustaendigeStelleData(FormData formData) { + return formData.getRepresentations().stream().filter(IS_BEHOERDE_METADATA).findAny() + .map(this::readBehoerdeMetadata) + .map(this::mapZustaendigeStelle) + .map(zustaendigeStelle -> formData.toBuilder().zustaendigeStelle(zustaendigeStelle).build()) + .orElse(formData); + } + + Map<String, String> readBehoerdeMetadata(IncomingFile metadata) { + try { + var mapper = new XmlMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + BayernData bayernData = mapper.readValue(metadata.getContentStream(), BayernData.class); + return bayernData.getFields().stream().filter(field -> nonNull(field.getValue())) + .collect(Collectors.toMap(BayernData.Field::getName, BayernData.Field::getValue)); + } catch (IOException e) { + LOG.error("Error parsing {}", BEHOERDE_METADATA_SUFFIX, e); + } + return Collections.emptyMap(); + } + + ZustaendigeStelle mapZustaendigeStelle(Map<String, String> behoerdeMetadata) { + return ZustaendigeStelle.builder() + .bezeichnung(behoerdeMetadata.get(KEY_BEHOERDE_ANZEIGE_NAME)) + .organisationseinheitenId(behoerdeMetadata.get(KEY_BEHOERDE_CALLER_ID)) + .gemeindeSchluessel(behoerdeMetadata.get(KEY_GEMEINDE_SCHLUESSEL_BP)) + .email(behoerdeMetadata.get(KEY_BEHOERDE_EMAIL)) + .amtlicherRegionalSchluessel(behoerdeMetadata.get(KEY_AMTLICHER_REGIONALSCHLUESSEL)) + .hausanschriftStrasse(behoerdeMetadata.get(KEY_BEHOERDE_HAUSANSCHRIFT_STRASSE)) + .hausanschriftOrt(behoerdeMetadata.get(KEY_BEHOERDE_HAUSANSCHRIFT_ORT)) + .hausanschriftPlz(behoerdeMetadata.get(KEY_BEHOERDE_HAUSANSCHRIFT_PLZ)) + .telefon(behoerdeMetadata.get(KEY_BEHOERDE_TELEFON)).build(); + } + + public boolean isResponsible(FormData formData) { + return formData.getRepresentations().stream().anyMatch(IS_BEHOERDE_METADATA); + } +} diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernData.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernData.java new file mode 100644 index 0000000000000000000000000000000000000000..3b1b26b1af38aa9432d7f2e9a9538984970af4f5 --- /dev/null +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernData.java @@ -0,0 +1,38 @@ +package de.ozgcloud.eingang.semantik.enginebased.afm; + +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@JacksonXmlRootElement(localName = "data") +@Getter +public class BayernData { + + @JacksonXmlProperty(localName = "field") + @JacksonXmlElementWrapper(useWrapping = false) + private List<Field> fields; + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Field { + + @JacksonXmlProperty(isAttribute = true) + String name; + + @JacksonXmlText + String value; + + } +} diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapperTest.java index c8ee29bd8101967aa0c44135d3faf80dccc80608..c7a45051739c5f16034940c5f98170d411f11c02 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmZustaendigeStelleMapperTest.java @@ -32,12 +32,11 @@ import java.util.Map; 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.common.formdata.FormDataTestFactory; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedMapper; -import de.ozgcloud.eingang.semantik.enginebased.afm.AfmZustaendigeStelleMapper; class AfmZustaendigeStelleMapperTest { @@ -45,6 +44,9 @@ class AfmZustaendigeStelleMapperTest { @Spy private AfmZustaendigeStelleMapper mapper; + @Mock + private BayernBehoerdeMetadataMapper bayernBehoerdeMetadataMapper; + @Nested class TestParseFormData { @@ -93,6 +95,18 @@ class AfmZustaendigeStelleMapperTest { assertThat(parsedFormData.getZustaendigeStelle().getEmail()).isEqualTo(AfmZustaendigeStelleTestFactory.EMAIL); } + + @Test + void shouldCallParseBayernMetadata() { + when(bayernBehoerdeMetadataMapper.isResponsible(any())).thenReturn(true); + var expectedFormData = FormDataTestFactory.create(); + when(bayernBehoerdeMetadataMapper.parseZustaendigeStelleData(any())).thenReturn(expectedFormData); + + var resultFormData = parseFormData(formData); + + assertThat(resultFormData).isEqualTo(expectedFormData); + } + } @Nested diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernBehoerdeMetadataMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernBehoerdeMetadataMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b3102fe48f22d2e44bb1e340b7df625f8a88e2f5 --- /dev/null +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/BayernBehoerdeMetadataMapperTest.java @@ -0,0 +1,262 @@ +package de.ozgcloud.eingang.semantik.enginebased.afm; + +import static de.ozgcloud.eingang.semantik.enginebased.afm.BayernBehoerdeMetadataMapper.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.File; +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.Spy; + +import de.itvsh.kop.common.test.TestUtils; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelleTestFactory; +import lombok.SneakyThrows; + +class BayernBehoerdeMetadataMapperTest { + + @Spy + private BayernBehoerdeMetadataMapper mapper; + + @Nested + class TestParseBehoerdeMetadata { + + private IncomingFile behoerdeMetadataFile; + + private FormData formData; + + @BeforeEach + void setUp() { + behoerdeMetadataFile = IncomingFileTestFactory.createBuilder().name(BayernBehoerdeMetadataMapper.BEHOERDE_METADATA_SUFFIX) + .build(); + formData = FormDataTestFactory.createBuilder() + .zustaendigeStelle(null) + .representation(behoerdeMetadataFile).build(); + } + + @Test + void shouldCallReadBehoerdeMetadata() { + mapper.parseZustaendigeStelleData(formData); + + verify(mapper).readBehoerdeMetadata(behoerdeMetadataFile); + } + + @Test + void shouldCallMapZustaendigeStelle() { + var behoerdeMetadata = Map.of("key", "value"); + doReturn(behoerdeMetadata).when(mapper).readBehoerdeMetadata(behoerdeMetadataFile); + + mapper.parseZustaendigeStelleData(formData); + + verify(mapper).mapZustaendigeStelle(behoerdeMetadata); + } + + @Test + void shouldSetParsedZustaendigeStelle() { + doReturn(Map.of("key", "value")).when(mapper).readBehoerdeMetadata(any()); + var zustaendigeStelle = ZustaendigeStelleTestFactory.create(); + doReturn(zustaendigeStelle).when(mapper).mapZustaendigeStelle(any()); + + var result = mapper.parseZustaendigeStelleData(formData); + + assertThat(result.getZustaendigeStelle()).isEqualTo(zustaendigeStelle); + } + } + + @Nested + class TestReadBehoerdeMetadata { + + private IncomingFile behoerdeMetadataXml; + + @SneakyThrows + @BeforeEach + void setUp() { + behoerdeMetadataXml = IncomingFileTestFactory.createBuilder() + .name(BayernBehoerdeMetadataMapper.BEHOERDE_METADATA_SUFFIX) + .file(new File(TestUtils.class.getClassLoader().getResource(BEHOERDE_METADATA_SUFFIX).toURI())).build(); + } + + @Test + void shouldParseBehoerdeAnzeigeName() { + var expectedValue = "Landratsamt XYZ (Testbehörde für BDA)"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_ANZEIGE_NAME, expectedValue); + } + + @Test + void shouldParseOrganisationEinheitId() { + var expectedValue = "87331322433"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_CALLER_ID, expectedValue); + } + + @Test + void shouldParseGemeindeSchluesselBp() { + var expectedValue = "09189155"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_GEMEINDE_SCHLUESSEL_BP, expectedValue); + } + + @Test + void shouldParseBehoerdeEmail() { + var expectedValue = "poststelle@testbehoerde.bayern"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_EMAIL, expectedValue); + } + + @Test + void shouldParseAmtlicherRegionalSchlussel() { + var expectedValue = "091890000000"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_AMTLICHER_REGIONALSCHLUESSEL, expectedValue); + } + + @Test + void shouldParseBehoerdeHausanschriftStrasse() { + var expectedValue = "Teststraße 1"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_HAUSANSCHRIFT_STRASSE, expectedValue); + } + + @Test + void shouldParseBehoerdeHausanschriftOrt() { + var expectedValue = "Musterstadt"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_HAUSANSCHRIFT_ORT, expectedValue); + } + + @Test + void shouldParseBehoerdeHausanschriftPlz() { + var expectedValue = "12345"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_HAUSANSCHRIFT_PLZ, expectedValue); + } + + @Test + void shouldParseBehoerdeTelefon() { + var expectedValue = "+49 123 45-0"; + + var metadata = mapper.readBehoerdeMetadata(behoerdeMetadataXml); + + assertThat(metadata).containsEntry(KEY_BEHOERDE_TELEFON, expectedValue); + } + } + + @Nested + class TestMapZuestaendigeStelle { + + private static final Map<String, String> BEHOERDE_METADATA = Map.of( + KEY_BEHOERDE_ANZEIGE_NAME, "beloerde-anzeige-name", + KEY_BEHOERDE_CALLER_ID, "behoerde-caller-id", + KEY_GEMEINDE_SCHLUESSEL_BP, "gemeinde-schluessel-bp", + KEY_BEHOERDE_EMAIL, "behoerde-email", + KEY_AMTLICHER_REGIONALSCHLUESSEL, "amtlicher-regionalschluessel", + KEY_BEHOERDE_HAUSANSCHRIFT_STRASSE, "behoerde-hausanschrift-strasse", + KEY_BEHOERDE_HAUSANSCHRIFT_ORT, "behoerde-hausanschrift-ort", + KEY_BEHOERDE_HAUSANSCHRIFT_PLZ, "behoerde-hausanschrift-plz", + KEY_BEHOERDE_TELEFON, "behoerde-telefon" + ); + + @Test + void shouldSetBezeichnung() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getBezeichnung()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_ANZEIGE_NAME)); + } + + @Test + void shouldSetOrganisationEinheitId() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_CALLER_ID)); + } + + @Test + void shouldSetGemeindeSchluessel() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getGemeindeSchluessel()).isEqualTo(BEHOERDE_METADATA.get(KEY_GEMEINDE_SCHLUESSEL_BP)); + } + + @Test + void shouldSetEmail() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getEmail()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_EMAIL)); + } + + @Test + void shouldSetAmtlicherRegionalSchluessel() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getAmtlicherRegionalSchluessel()).isEqualTo(BEHOERDE_METADATA.get(KEY_AMTLICHER_REGIONALSCHLUESSEL)); + } + + @Test + void shouldSetHausanschriftStrasse() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getHausanschriftStrasse()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_HAUSANSCHRIFT_STRASSE)); + } + + @Test + void shouldSetHausanschriftOrt() { + var zusatendigeStelle = mapZustaendigeStelle(); + + assertThat(zusatendigeStelle.getHausanschriftOrt()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_HAUSANSCHRIFT_ORT)); + } + + @Test + void shouldSetHausanschriftPlz() { + var zustaendigeStelle = mapZustaendigeStelle(); + + assertThat(zustaendigeStelle.getHausanschriftPlz()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_HAUSANSCHRIFT_PLZ)); + } + + @Test + void shouldSetTelefon() { + var zusatendigeStelle = mapZustaendigeStelle(); + + assertThat(zusatendigeStelle.getTelefon()).isEqualTo(BEHOERDE_METADATA.get(KEY_BEHOERDE_TELEFON)); + } + + private ZustaendigeStelle mapZustaendigeStelle() { + return mapper.mapZustaendigeStelle(BEHOERDE_METADATA); + } + } + + @Test + void shouldApproveResponsibility() { + var formData = FormDataTestFactory.createBuilder() + .representation(IncomingFileTestFactory.createBuilder().name(BayernBehoerdeMetadataMapper.BEHOERDE_METADATA_SUFFIX) + .build()).build(); + + var isResponsible = mapper.isResponsible(formData); + + assertThat(isResponsible).isTrue(); + } +} \ No newline at end of file diff --git a/semantik-adapter/src/test/resources/behoerde_metadata.xml b/semantik-adapter/src/test/resources/behoerde_metadata.xml new file mode 100644 index 0000000000000000000000000000000000000000..66b1f000dd1af9e077657cab9f67bf0d3710b32f --- /dev/null +++ b/semantik-adapter/src/test/resources/behoerde_metadata.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<data xmlns="http://xmlns.cit.de/assistants/store" name="myForm" class="de.cit.assistants.DataBean"> + <field type="string" readonly="true" name="behoerde_anzeige_name">Landratsamt XYZ (Testbehörde für BDA)</field> + <field type="string" readonly="true" name="behoerde_caller_id">87331322433</field> + <field type="string" readonly="true" name="behoerde_pki_email"></field> + <field type="string" readonly="true" name="behoerde_link"> + https://redesign.bayernportal.bayern.de/dokumente/behoerde/87331322433</field> + <field type="string" readonly="true" name="behoerde_sicherer_kontakt_link"></field> + <field type="string" readonly="true" name="behoerde_postkorb_eakte"></field> + <field type="string" readonly="true" name="behoerde_organisationseinheit_eakte"></field> + <field type="string" readonly="true" name="gemeinde_schluessel_bp">09189155</field> + <field type="string" readonly="true" name="amtlicher_regionalschluessel">091890000000</field> + <field type="string" readonly="true" name="behoerde_email">poststelle@testbehoerde.bayern</field> + <field type="string" readonly="true" name="behoerde_telefon">+49 123 45-0</field> + <field type="string" readonly="true" name="behoerde_telefax">+49 12 45-7</field> + <field type="string" readonly="true" name="behoerde_hausanschrift_strasse">Teststraße 1</field> + <field type="string" readonly="true" name="behoerde_hausanschrift_plz">12345</field> + <field type="string" readonly="true" name="behoerde_hausanschrift_ort">Musterstadt</field> + <field type="string" readonly="true" name="behoerde_safeId"></field> + <field type="string" readonly="true" name="dvdv_praefix">bab</field> + <field type="string" readonly="true" name="dvdv_kennung">09189</field> +</data> \ No newline at end of file