diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java index 29e2c0834d9a05e11519f371cdd2686faa549ed4..d7fa85a1d87e3ac6776068e6a5a062a8b96de3d3 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapper.java @@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.bind.Binder; 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; @@ -67,78 +66,52 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { @Override public FormData parseFormData(FormData formData) { - try { - return adaptFormDataWithPossibleException(formData); - } catch (TechnicalException exception) { - logWarningForFailure(exception); - return formData; - } + return formData.toBuilder() + .clearZustaendigeStelles() + .zustaendigeStelles(getZustaendigeStelles(formData)) + .build(); } - void logWarningForFailure(Exception exception) { - LOG.warn("Failed mapping Zustaendigestelle of Mantelantrag: %s".formatted(exception.getMessage())); + List<ZustaendigeStelle> getZustaendigeStelles(FormData formData) { + var fieldMap = formData.getFormData(); + var matchingSlots = getMatchingSlots(fieldMap); + if (matchingSlots.isEmpty()) { + logErrorForNoMatchingIdentifiers(); + } + return matchingSlots.stream() + .map(slotIndex -> getZustaendigeStelle(fieldMap, slotIndex)) + .toList(); } - FormData adaptFormDataWithPossibleException(FormData formData) { - var fieldMap = formData.getFormData(); - var slotIndex = findSlotIndex(fieldMap); - return adaptFormDataWithValueGetter(formData, field -> getFieldByKeyOrEmpty( + ZustaendigeStelle getZustaendigeStelle(Map<String, Object> fieldMap, int slotIndex) { + UnaryOperator<String> getValueOrEmpty = 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 matchingSlots = getMatchingSlots(fieldMap); - verifyOneMatchingIdentifier(matchingSlots); - return matchingSlots.getFirst(); - } - - private void verifyOneMatchingIdentifier(List<Integer> matchingSlots) { - if (matchingSlots.size() != 1) { - var message = getMultipleSlotsMessage(matchingSlots); - if (matchingSlots.isEmpty()) { - throw new TechnicalException(message); - } else { - logWarningForUnexpected(message); - } + logWarningForEmptyOrganisationseinheitId(slotIndex); } + return ZustaendigeStelle.builder() + .organisationseinheitenId(organisationseinheitId) + .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(); } - void logWarningForUnexpected(String message) { - LOG.warn("Unexpected Zustaendigestelle in Mantelantrag: %s".formatted(message)); + void logWarningForEmptyOrganisationseinheitId(int slotIndex) { + LOG.warn("[Mantelantrag] OrganisationseinheitId for slot {} is empty!", slotIndex); } - String getMultipleSlotsMessage(List<Integer> matchingSlots) { - return "Found %d matching nachrichtenbroker addresses! Expected one of '%s'.".formatted(matchingSlots.size(), - Strings.join(xtaIdentifiers, ',')); + void logErrorForNoMatchingIdentifiers() { + LOG.error("[Mantelantrag] No matching Zustaendigestelle found! For identifiers: '{}'.", Strings.join(xtaIdentifiers, ',')); } - private List<Integer> getMatchingSlots(Map<String, Object> fieldMap) { + List<Integer> getMatchingSlots(Map<String, Object> fieldMap) { return IntStream.range(0, 3) .filter(slotIndex -> xtaIdentifiers.contains(getXtaIdentifierOfSlot(fieldMap, slotIndex))) .boxed() diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java index 2825ced4320061e6c7c2c5f51b34cfa2034830b3..e80eeca2598ef00dc45d827401744d80eb10ba4c 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragITCase.java @@ -1,5 +1,6 @@ package de.ozgcloud.eingang.semantik.formbased.mantelantrag; +import static de.ozgcloud.eingang.common.formdata.FormDataTestFactory.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -7,76 +8,154 @@ import static org.mockito.Mockito.*; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.BeforeAll; 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.springframework.beans.factory.annotation.Autowired; 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 org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; 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.common.formdata.ZustaendigeStelle; -import de.ozgcloud.eingang.router.VorgangService; +import de.ozgcloud.eingang.router.VorgangRemoteService; 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.identifiers=afmsh:ozg-cloud-utopia-test" }) +@SpringBootTest(classes = Application.class) 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; + VorgangRemoteService vorgangRemoteService; @SpyBean SemantikAdapter semantikAdapter; + @Captor + ArgumentCaptor<FormData> formDataCaptor; + private FormData formData; + + @Captor + ArgumentCaptor<Optional<String>> oeIdCaptor; + + @Autowired + MantelantragZustaendigeStelleMapper mantelantragZustaendigeStelleMapper; + + static List<String> xtaIdentifiers = Collections.emptyList(); + + @BeforeEach + void mock() { + clearInvocations(vorgangRemoteService); + doReturn(VORGANG_ID).when(vorgangRemoteService).createVorgang(any(FormData.class), any()); + formData = prepareTestData(); + mantelantragZustaendigeStelleMapper.init(); + } + + @DynamicPropertySource + static void dynamicProperties(DynamicPropertyRegistry registry) { + registry.add("ozgcloud.xta.identifiers", () -> xtaIdentifiers); + } + + @DisplayName("without matching zustaendige stelle") @Nested - class TestZustaendigeStelle { + class TestWithoutMatchingZustaendigeStelle { - @Captor - ArgumentCaptor<FormData> formDataCaptor; + @BeforeAll + static void setup() { + xtaIdentifiers = List.of("afmsh:unknown"); + } - private static final String VORGANG_ID_1 = "vorgangId1"; + @DisplayName("should create one vorgang") + @Test + void shouldCreateOneVorgang() { + semantikAdapter.processFormData(formData); + verify(vorgangRemoteService, times(1)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture()); + assertThat(oeIdCaptor.getValue()).isEmpty(); + } + } - @BeforeEach - void mock() { - doReturn(VORGANG_ID_1).when(vorgangService).createVorgang(any()); + @DisplayName("with one matching zustaendige stelle") + @Nested + class TestWithOneMatchingZustaendigeStelle { + @BeforeAll + static void setup() { + xtaIdentifiers = List.of("afmsh:ozg-cloud-utopia-test"); } - @DisplayName("should return first vorgangId") + @DisplayName("should create one vorgang") @Test - void shouldReturnFirstVorgangId() { - var result = semantikAdapter.processFormData(prepareTestData()); + void shouldCreateOneVorgang() { + semantikAdapter.processFormData(formData); - assertThat(result).isEqualTo(VORGANG_ID_1); + verify(vorgangRemoteService, times(1)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture()); + assertThat(oeIdCaptor.getValue()).contains("123"); } + } - @DisplayName("should pass organisationseinheit id to create vorgang") + @DisplayName("with two matching zustaendige stelle") + @Nested + class TestWithTwoMatchingZustaendigeStelle { + + @BeforeAll + static void setup() { + xtaIdentifiers = List.of("afmsh:ozg-cloud-utopia-test", "gae:ozg-cloud-itcase-test"); + } + + @DisplayName("should create two vorangs with partially matching zustaendigeStelle") + @Test + void shouldCreateTwoVorangsWithPartiallyMatchingZustaendigeStelle() { + semantikAdapter.processFormData(formData); + + verify(vorgangRemoteService, times(2)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture()); + assertThat(oeIdCaptor.getAllValues()).contains(Optional.of("123"), Optional.of("444")); + } + } + + @DisplayName("with three matching zustaendige stelles") + @Nested + class TestWithThreeMatchingZustaendigeStelles { + + @BeforeAll + static void setup() { + xtaIdentifiers = List.of("afmsh:ozg-cloud-utopia-test", "gae:ozg-cloud-itcase-test", "afmsh:ozg-cloud-bad-segeberg-kreis"); + } + + @DisplayName("should create three vorgangs") @Test - void shouldPassOrganisationseinheitIdToCreateVorgang() { - semantikAdapter.processFormData(prepareTestData()); + void shouldCreateThreeVorgangs() { + semantikAdapter.processFormData(formData); - verify(vorgangService).createVorgang(formDataCaptor.capture()); - assertThat(formDataCaptor.getValue().getZustaendigeStelles()) - .extracting(ZustaendigeStelle::getOrganisationseinheitenId) - .containsExactly("123"); + verify(vorgangRemoteService, times(3)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture()); + assertThat(oeIdCaptor.getAllValues()).contains(Optional.of("123"), Optional.of("321"), Optional.of("444")); } + } + + @DisplayName("should return first vorgangId") + @Test + void shouldReturnFirstVorgangId() { + var result = semantikAdapter.processFormData(formData); + assertThat(result).isEqualTo(VORGANG_ID); } private FormData prepareTestData() { diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java index 377ff70a5036a54bc7e362c198a8339febc48dc1..782209dff8ebd6174a29942c0812b90f8b5753ca 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragZustaendigeStelleMapperTest.java @@ -1,6 +1,7 @@ package de.ozgcloud.eingang.semantik.formbased.mantelantrag; import static de.ozgcloud.eingang.semantik.formbased.mantelantrag.MantelantragZustaendigeStelleMapper.*; +import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -18,13 +19,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import 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; @@ -107,53 +105,104 @@ class MantelantragZustaendigeStelleMapperTest { } } - @DisplayName("adapt form data") + @DisplayName("parse form data") @Nested - class TestAdaptFormData { + class TestParseFormData { + + private FormData formData; @Mock + private ZustaendigeStelle zustaendigeStelle; + + @BeforeEach + void mock() { + formData = FormDataTestFactory.create(); + } + + @DisplayName("should override zustaendige stelles") + @Test + void shouldOverrideZustaendigeStelles() { + doReturn(List.of(zustaendigeStelle)).when(mapper).getZustaendigeStelles(formData); + + var result = mapper.parseFormData(formData); + + assertThat(result.getZustaendigeStelles()).containsExactly(zustaendigeStelle); + } + + @DisplayName("should keep other formdata fields") + @Test + void shouldKeepOtherFormdataFields() { + doReturn(formData.getZustaendigeStelles()).when(mapper).getZustaendigeStelles(formData); + + var result = mapper.parseFormData(formData); + + assertThat(result).usingRecursiveComparison().isEqualTo(formData); + } + } + + @DisplayName("get zustaendige stelles") + @Nested + class TestGetZustaendigeStelles { + private FormData formData; @Mock - private FormData formData2; + private Map<String, Object> fieldMap; + + @Mock + private ZustaendigeStelle stelle1; + + @Mock + private ZustaendigeStelle stelle2; + + @Mock + private ZustaendigeStelle stelle3; - @DisplayName("should return adapted value") + @BeforeEach + void mock() { + formData = FormDataTestFactory.createBuilder() + .formData(fieldMap) + .build(); + } + + @DisplayName("should return") @Test - void shouldReturnAdaptedValue() { - doReturn(formData2).when(mapper).adaptFormDataWithPossibleException(formData); + void shouldReturn() { + doReturn(emptyList()).when(mapper).getMatchingSlots(fieldMap); - var resultFormData = mapper.parseFormData(formData); + var result = mapper.getZustaendigeStelles(formData); - assertThat(resultFormData).isEqualTo(formData2); + assertThat(result).isEmpty(); } - @DisplayName("should return original value with exception") + @DisplayName("should log error for no matching identifiers") @Test - void shouldReturnOriginalValueWithException() { - doThrow(new TechnicalException("some error")).when(mapper).adaptFormDataWithPossibleException(formData); + void shouldLogErrorForNoMatchingIdentifiers() { + doReturn(emptyList()).when(mapper).getMatchingSlots(fieldMap); - var resultFormData = mapper.parseFormData(formData); + mapper.getZustaendigeStelles(formData); - assertThat(resultFormData).isEqualTo(formData); + verify(mapper).logErrorForNoMatchingIdentifiers(); } - @DisplayName("should log warning with exception") + @DisplayName("should return with three zustaendige stelle") @Test - void shouldLogWarningWithException() { - var exception = new TechnicalException("some error"); - doThrow(exception).when(mapper).adaptFormDataWithPossibleException(formData); + void shouldReturnWithThreeZustaendigeStelle() { + doReturn(List.of(0, 1, 2)).when(mapper).getMatchingSlots(fieldMap); + doReturn(stelle1).when(mapper).getZustaendigeStelle(fieldMap, 0); + doReturn(stelle2).when(mapper).getZustaendigeStelle(fieldMap, 1); + doReturn(stelle3).when(mapper).getZustaendigeStelle(fieldMap, 2); - mapper.parseFormData(formData); + var result = mapper.getZustaendigeStelles(formData); - verify(mapper).logWarningForFailure(exception); + assertThat(result).containsExactly(stelle1, stelle2, stelle3); } } - @DisplayName("adapt form data with possible exception") + @DisplayName("get zustaendige stelle") @Nested - class TestAdaptFormDataWithPossibleException { + class TestGetZustaendigeStelle { - 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, @@ -162,17 +211,8 @@ class MantelantragZustaendigeStelleMapperTest { 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( @@ -180,22 +220,6 @@ class MantelantragZustaendigeStelleMapperTest { getOrganisationseinheitIDFieldName(2), "", getOrganisationseinheitIDFieldName(10), "1111111" )); - formData = FormDataTestFactory.createBuilder() - .clearZustaendigeStelles() - .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") @@ -204,7 +228,7 @@ class MantelantragZustaendigeStelleMapperTest { void shouldMapOrganisationseinheitId(int slotIndex) { mockWithOEID(slotIndex, TARGET_OEID); - var zustaendigeStelle = getAdaptedZustaendigeStelle(); + var zustaendigeStelle = getZustaendigeStelle(slotIndex); assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(TARGET_OEID); } @@ -213,62 +237,60 @@ class MantelantragZustaendigeStelleMapperTest { return mapper.getNameForSlotIndex(ORGANISATIONSEINHEIT_ID_FIELD, slotIndex); } - @DisplayName("should throw if organistaionseinheitId is missing") + @DisplayName("should log warning if organistaionseinheitId is missing") @ParameterizedTest @ValueSource(ints = { 0, 1, 2 }) - void shouldThrowIfOrganistationseinheitIdIsMissing(int slotIndex) { - doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap); + void shouldLogWarningIfOrganistaionseinheitIdIsMissing(int slotIndex) { + getZustaendigeStelle(slotIndex); - 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); + verify(mapper).logWarningForEmptyOrganisationseinheitId(slotIndex); } @DisplayName("should map optional field") @ParameterizedTest - @MethodSource("fieldNameAndSlotIndex") + @MethodSource("generateFieldNameAndSlotIndex") void shouldMapOptionalField(int slotIndex, String fieldName) { mockWithSomeOEID(slotIndex); - fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), TARGET_OPTIONAL_FIELD_VALUE); + var optionalFieldValue = "value of '%s'".formatted(fieldName); + fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), optionalFieldValue); - var zustaendigeStelle = getAdaptedZustaendigeStelle(); + var zustaendigeStelle = getZustaendigeStelle(slotIndex); - assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEqualTo(TARGET_OPTIONAL_FIELD_VALUE); + assertThat(getExpectedValueByFieldName(zustaendigeStelle, fieldName)).isEqualTo(optionalFieldValue); } @DisplayName("should map missing optional fields to empty") @ParameterizedTest - @MethodSource("fieldNameAndSlotIndex") + @MethodSource("generateFieldNameAndSlotIndex") void shouldMapMissingOptionalFieldsToEmpty(int slotIndex, String fieldName) { mockWithSomeOEID(slotIndex); - var zustaendigeStelle = getAdaptedZustaendigeStelle(); + var zustaendigeStelle = getZustaendigeStelle(slotIndex); - assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty(); + assertThat(getExpectedValueByFieldName(zustaendigeStelle, fieldName)).isEmpty(); } @DisplayName("should map empty optional fields to empty") @ParameterizedTest - @MethodSource("fieldNameAndSlotIndex") + @MethodSource("generateFieldNameAndSlotIndex") void shouldMapEmptyOptionalFieldsToEmpty(int slotIndex, String fieldName) { mockWithSomeOEID(slotIndex); fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), ""); - var zustaendigeStelle = getAdaptedZustaendigeStelle(); + var zustaendigeStelle = getZustaendigeStelle(slotIndex); - assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty(); + assertThat(getExpectedValueByFieldName(zustaendigeStelle, fieldName)).isEmpty(); } - private String getExpectedByFieldName(ZustaendigeStelle zustaendigeStelle, String fieldName) { + private static Stream<Arguments> generateFieldNameAndSlotIndex() { + return Stream.of(0, 1, 2) + .flatMap(slotIndex -> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR + .keySet().stream() + .map(fieldName -> Arguments.of(slotIndex, fieldName)) + ); + } + + private String getExpectedValueByFieldName(ZustaendigeStelle zustaendigeStelle, String fieldName) { var valueExtractor = FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR.get(fieldName); return valueExtractor.apply(zustaendigeStelle); } @@ -279,25 +301,20 @@ class MantelantragZustaendigeStelleMapperTest { 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.getZustaendigeStelles().getFirst(); + private ZustaendigeStelle getZustaendigeStelle(int slotIndex) { + return mapper.getZustaendigeStelle(fieldMap, slotIndex); } } - @DisplayName("find slot index") + @DisplayName("get matching slots") @Nested - class TestFindSlotIndex { + class TestGetMatchingSlots { private Map<String, Object> fieldMap; - @Captor - private ArgumentCaptor<String> warningCaptor; - @BeforeEach void mock() { fieldMap = new HashMap<>(Map.of( @@ -306,15 +323,23 @@ class MantelantragZustaendigeStelleMapperTest { )); } - @DisplayName("should return matching slot") + @DisplayName("should return empty") + @Test + void shouldReturnEmpty() { + var resultSlotIndices = mapper.getMatchingSlots(fieldMap); + + assertThat(resultSlotIndices).isEmpty(); + } + + @DisplayName("should return matching slots") @ParameterizedTest @ValueSource(ints = { 0, 1, 2 }) void shouldReturnMatchingSlot(int slotIndex) { fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER); - var resultSlotIndex = mapper.findSlotIndex(fieldMap); + var resultSlotIndices = mapper.getMatchingSlots(fieldMap); - assertThat(resultSlotIndex).isEqualTo(slotIndex); + assertThat(resultSlotIndices).containsExactly(slotIndex); } @DisplayName("should return matching slot with upper-/lowercase difference in identifiers") @@ -323,33 +348,14 @@ class MantelantragZustaendigeStelleMapperTest { void shouldReturnMatchingSlotWithUppercaseIdentifier(int slotIndex) { fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER2UPPERCASE); - var resultSlotIndex = mapper.findSlotIndex(fieldMap); + var resultSlotIndex = mapper.getMatchingSlots(fieldMap); - assertThat(resultSlotIndex).isEqualTo(slotIndex); + assertThat(resultSlotIndex).containsExactly(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("should log warning if multiple slots match") - @Test - void shouldLogWarningIfMultipleSlotsMatch() { - fieldMap.put(getZustaendigeStelleName(0), IDENTIFIER2); - fieldMap.put(getZustaendigeStelleName(2), IDENTIFIER); - - mapper.findSlotIndex(fieldMap); - - verify(mapper).logWarningForUnexpected(warningCaptor.capture()); - assertThat(warningCaptor.getValue()).isEqualTo(mapper.getMultipleSlotsMessage(List.of(0, 2))); - } } @DisplayName("get name for slot index") diff --git a/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 index 6c7c4e94203d54e765188787a2ef449b7dfcda02..3872cdb8d4bbff8112620fdc044f0bc70aeb6468 100644 --- 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 @@ -83,7 +83,7 @@ <zustellung_nachrichtenbroker2>afmsh:ozg-cloud-bad-segeberg-kreis</zustellung_nachrichtenbroker2> <zustellung_email_ln2/> <zustellung_webservice2/> - <kontaktsystem_oeid3/> + <kontaktsystem_oeid3>444</kontaktsystem_oeid3> <OrganisationseinheitenBEZEICHNUNG3/> <zust_strasse3/> <zust_hausnummer3/> @@ -93,7 +93,7 @@ <zust_telefonnummer3/> <zust_faxnummer3/> <zust_emailadresse3/> - <zustellung_nachrichtenbroker3/> + <zustellung_nachrichtenbroker3>gae:ozg-cloud-itcase-test</zustellung_nachrichtenbroker3>> <zustellung_email_ln3/> <zustellung_webservice3/> <grund>Hilfe</grund>