diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapper.java index dd7563185835c2c396b49c0e30460191c0f9b2df..a70263b2acc1215ed495c94698401bc9a814db8f 100644 --- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapper.java +++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapper.java @@ -1,8 +1,8 @@ package de.ozgcloud.eingang.semantik.formbased; -import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.UnaryOperator; import java.util.stream.IntStream; import org.apache.commons.collections.MapUtils; @@ -22,28 +22,15 @@ public class MantelantragFormBasedMapper implements FormBasedMapper { static final String MANTELANTRAG_FORM_ID = "maa_mantelantrag/maa_mantelantrag_pvog"; - static final List<String> ZUSTELLUNG_NACHRICHTENBROKER_SLOTS = List.of( - "zustellung_nachrichtenbroker", - "zustellung_nachrichtenbroker2", - "zustellung_nachrichtenbroker3" - ); + static final String ZUSTELLUNG_NACHRICHTENBROKER_FIELD = "zustellung_nachrichtenbroker"; - static final List<String> KONTAKTSYSTEM_OEID_SLOTS = List.of( - "kontaktsystem_oeid", - "kontaktsystem_oeid2", - "kontaktsystem_oeid3" - ); - - @Override - public FormData adaptFormData(FormData formData) { - return formData.toBuilder() - .zustaendigeStelle(ZustaendigeStelle.builder() - .organisationseinheitenId( - getOrganisationseinheitID(formData.getFormData()) - ) - .build()) - .build(); - } + 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"; @Override public boolean isResponsible(FormData formData) { @@ -53,34 +40,54 @@ public class MantelantragFormBasedMapper implements FormBasedMapper { .equals(MANTELANTRAG_FORM_ID); } - String getOrganisationseinheitID(Map<String, Object> fieldMap) { - var organisationseinheitId = getFieldByKey( + @Override + public FormData adaptFormData(FormData formData) { + var fieldMap = formData.getFormData(); + var slotIndex = findSlotIndex(fieldMap); + UnaryOperator<String> getValueOrEmpty = field -> getFieldByKey( fieldMap, - KONTAKTSYSTEM_OEID_SLOTS.get( - findSlotIndex(fieldMap) - ) - ); + getNameForSlotIndex(field, slotIndex) + ).orElse(""); + var organisationseinheitId = getValueOrEmpty.apply(ORGANISATIONSEINHEIT_ID_FIELD); + if (organisationseinheitId.isBlank()) { throw new TechnicalException("OrganistaionseinheitId not found in Mantelantrag!"); } - return organisationseinheitId; + + return formData.toBuilder() + .zustaendigeStelle(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()) + .build(); } int findSlotIndex(Map<String, Object> fieldMap) { var identifier = environment.getProperty("ozgcloud.xta.identifier"); - return IntStream.range(0, ZUSTELLUNG_NACHRICHTENBROKER_SLOTS.size()) + return IntStream.range(0, 3) .filter(slotIndex -> getFieldByKey( - fieldMap, - ZUSTELLUNG_NACHRICHTENBROKER_SLOTS.get(slotIndex) - ).equals(identifier)) + fieldMap, + getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex) + ) + .map(value -> value.equals(identifier)) + .orElse(false) + ) .findFirst() .orElseThrow(() -> new TechnicalException("No matching nachrichtenbroker address '%s' found!".formatted(identifier))); } - private String getFieldByKey(Map<String, Object> fieldMap, String key) { + String getNameForSlotIndex(String name, int slotIndex) { + return slotIndex > 0 ? "%s%d".formatted(name, slotIndex + 1) : name; + } + + private Optional<String> getFieldByKey(Map<String, Object> fieldMap, String key) { return Optional.ofNullable(MapUtils.getString(fieldMap, key)) - .orElse("") - .trim(); + .map(String::trim); } } diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapperTest.java index e6ee3dcc6e8f66138693ba68a6c4b0d2de804f66..744115a5843d2b8e2b4bcb3b66c959b5fad093be 100644 --- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapperTest.java +++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/MantelantragFormBasedMapperTest.java @@ -6,12 +6,16 @@ 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; @@ -22,6 +26,7 @@ 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 MantelantragFormBasedMapperTest { private final static String TARGET_OEID = "123456"; @@ -73,25 +78,140 @@ class MantelantragFormBasedMapperTest { private FormData formData; - @Mock private Map<String, Object> fieldMap; @BeforeEach void mock() { + fieldMap = new HashMap<>(Map.of( + getOrganisationseinheitIDFieldName(1), " ", + getOrganisationseinheitIDFieldName(2), "", + getOrganisationseinheitIDFieldName(10), "1111111" + )); formData = FormDataTestFactory.createBuilder() .formData(fieldMap) .build(); - doReturn(TARGET_OEID).when(mapper).getOrganisationseinheitID(fieldMap); } - @DisplayName("should return adapted formdata") + @DisplayName("should keep form data except zustaendigestelle") @Test - void shouldReturnAdaptedFormdata() { - var formDataResult = mapper.adaptFormData(formData); + void shouldKeepFormDataExceptZustaendigestelle() { + doReturn(10).when(mapper).findSlotIndex(fieldMap); + + var resultFormData = mapper.adaptFormData(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(); - var zustaendigeStelle = formDataResult.getZustaendigeStelle(); 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); + } + + 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 + ); + + @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 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)) + ); + } + + 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.adaptFormData(formData); + return formDataResult.getZustaendigeStelle(); + } + } @DisplayName("find slot index") @@ -105,8 +225,8 @@ class MantelantragFormBasedMapperTest { when(environment.getProperty("ozgcloud.xta.identifier")).thenReturn(IDENTIFIER); fieldMap = new HashMap<>(Map.of( - "zustellung_nachrichtenbroker2", "unknown", - "zustellung_nachrichtenbroker3", "" + getZustaendigeStelleName(1), "unknown", + getZustaendigeStelleName(2), "" )); } @@ -114,13 +234,17 @@ class MantelantragFormBasedMapperTest { @ParameterizedTest @ValueSource(ints = { 0, 1, 2 }) void shouldReturnMatchingSlot(int slotIndex) { - fieldMap.put(ZUSTELLUNG_NACHRICHTENBROKER_SLOTS.get(slotIndex), IDENTIFIER); + 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() { @@ -129,39 +253,24 @@ class MantelantragFormBasedMapperTest { } } - @DisplayName("get organisationseinheitID by slot") + @DisplayName("get name for slot index") @Nested - class TestGetOrganisationseinheitIdBySlot { - private Map<String, Object> fieldMap; - - @BeforeEach - void mock() { - fieldMap = new HashMap<>(Map.of( - "kontaktsystem_oeid2", " ", - "kontaktsystem_oeid3", "" - )); - } - - @DisplayName("should return oeid of slot") + class TestGetNameForSlotIndex { + @DisplayName("should return name") @ParameterizedTest - @ValueSource(ints = { 0, 1, 2 }) - void shouldReturnOeidOfSlot(int slotIndex) { - fieldMap.put(KONTAKTSYSTEM_OEID_SLOTS.get(slotIndex), TARGET_OEID); - doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap); + @MethodSource("nameAndSlotIndexAndExpected") + void shouldReturnName(String name, int slotIndex, String expected) { + var resultName = mapper.getNameForSlotIndex(name, slotIndex); - var oeidResult = mapper.getOrganisationseinheitID(fieldMap); - - assertThat(oeidResult).isEqualTo(TARGET_OEID); + assertThat(resultName).isEqualTo(expected); } - @DisplayName("should throw if missing") - @ParameterizedTest - @ValueSource(ints = { 0, 1, 2 }) - void shouldThrowIfMissing(int slotIndex) { - doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap); - - assertThatThrownBy(() -> mapper.getOrganisationseinheitID(fieldMap)) - .isInstanceOf(TechnicalException.class); + private static Stream<Arguments> nameAndSlotIndexAndExpected() { + return Stream.of( + Arguments.of("name", 0, "name"), + Arguments.of("name", 1, "name2"), + Arguments.of("name", 2, "name3") + ); } } }