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 9ddc1287c6c7433070c59de09264b0f8156bcc75..840740752266df48db870f1f77073a1cf04fd85e 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 @@ -1,11 +1,20 @@ package de.ozgcloud.eingang.semantik.formbased.mantelantrag; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.function.UnaryOperator; import java.util.stream.IntStream; +import jakarta.annotation.PostConstruct; + import org.apache.commons.collections.MapUtils; +import org.apache.logging.log4j.util.Strings; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @@ -32,6 +41,18 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { static final String TELEFON_FIELD = "telefon"; private final Environment environment; + private Set<String> xtaIdentifiers; + + @PostConstruct + void init() { + xtaIdentifiers = new HashSet<>(getIdentifierList()); + } + + List<String> getIdentifierList() { + return Binder.get(environment) + .bind("ozgcloud.xta.identifiers", Bindable.listOf(String.class)) + .orElseGet(Collections::emptyList); + } @Override public boolean isResponsible(FormData formData) { @@ -85,15 +106,28 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { } int findSlotIndex(Map<String, Object> fieldMap) { - var identifier = environment.getProperty("ozgcloud.xta.identifier"); + var matchingSlots = getMatchingSlots(fieldMap); + verifyOneMatchingIdentifier(matchingSlots); + return matchingSlots.getFirst(); + } + + private void verifyOneMatchingIdentifier(List<Integer> matchingSlots) { + if (matchingSlots.size() != 1) { + throw new TechnicalException( + "Found %d matching nachrichtenbroker addresses! Expected one of '%s'." + .formatted(matchingSlots.size(), Strings.join(xtaIdentifiers, ','))); + } + } + + private List<Integer> getMatchingSlots(Map<String, Object> fieldMap) { 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))); + .filter(slotIndex -> xtaIdentifiers.contains(getXtaIdentifierOfSlot(fieldMap, slotIndex))) + .boxed() + .toList(); + } + + private String getXtaIdentifierOfSlot(Map<String, Object> fieldMap, int slotIndex) { + return getFieldByKeyOrEmpty(fieldMap, getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex)); } String getNameForSlotIndex(String name, int slotIndex) { 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 9d2094d600c3eed7495003e5dfa9ba969a9b4599..a4951086c82837ebc3c01ef5f19b8833882b0e3c 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 @@ -29,7 +29,7 @@ import de.ozgcloud.eingang.semantik.enginebased.formsolutions.FormSolutionsEngin import lombok.SneakyThrows; @ActiveProfiles({ "local", "itcase" }) -@SpringBootTest(classes = Application.class, properties = { "ozgcloud.xta.identifier=afmsh:ozg-cloud-utopia-test" }) +@SpringBootTest(classes = Application.class, properties = { "ozgcloud.xta.identifiers=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"; 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 f03169a6704aae741e3234b82aff876448b027d6..e7b9d8009f1087cb274e2fe1e9459c038d18da04 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 @@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Stream; @@ -20,7 +21,6 @@ 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; @@ -31,13 +31,18 @@ import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; class MantelantragZustaendigeStelleMapperTest { private final static String TARGET_OEID = "123456"; private static final String IDENTIFIER = "gea:test"; + private static final String IDENTIFIER2 = "dfad:test"; + private static final List<String> IDENTIFIERS = List.of(IDENTIFIER, IDENTIFIER2, "aa:other"); @Spy @InjectMocks private MantelantragZustaendigeStelleMapper mapper; - @Mock - private Environment environment; + @BeforeEach + void mock() { + doReturn(IDENTIFIERS).when(mapper).getIdentifierList(); + mapper.init(); + } @DisplayName("is responsible") @Nested @@ -277,8 +282,6 @@ class MantelantragZustaendigeStelleMapperTest { @BeforeEach void mock() { - when(environment.getProperty("ozgcloud.xta.identifier")).thenReturn(IDENTIFIER); - fieldMap = new HashMap<>(Map.of( getZustaendigeStelleName(1), "unknown", getZustaendigeStelleName(2), "" @@ -306,6 +309,16 @@ class MantelantragZustaendigeStelleMapperTest { assertThatThrownBy(() -> mapper.findSlotIndex(fieldMap)) .isInstanceOf(TechnicalException.class); } + + @DisplayName("should throw if multiple slots match") + @Test + void shouldThrowIfMultipleSlotsMatch() { + fieldMap.put(getZustaendigeStelleName(0), IDENTIFIER2); + fieldMap.put(getZustaendigeStelleName(2), IDENTIFIER); + + assertThatThrownBy(() -> mapper.findSlotIndex(fieldMap)) + .isInstanceOf(TechnicalException.class); + } } @DisplayName("get name for slot index")