diff --git a/common/src/main/java/de/ozgcloud/eingang/EingangAspectPointcuts.java b/common/src/main/java/de/ozgcloud/eingang/EingangAspectPointcuts.java new file mode 100644 index 0000000000000000000000000000000000000000..5a4eafc31fba2d3e5913e47c6e41207412276d10 --- /dev/null +++ b/common/src/main/java/de/ozgcloud/eingang/EingangAspectPointcuts.java @@ -0,0 +1,26 @@ +package de.ozgcloud.eingang; + +import org.aspectj.lang.annotation.Pointcut; + +public class EingangAspectPointcuts { + + @Pointcut("execution(public * *(..))") + void anyPublicMethods() { + // aspect pointcut - no implementation needed + } + + @Pointcut("within(de.ozgcloud..*)") + void anythingInOzgCloud() { + // aspect pointcut - no implementation needed + } + + @Pointcut("anyPublicMethods() && anythingInOzgCloud()") + void anyPublicMethodInOzgCloud() { + // aspect pointcut - no implementation needed + } + + @Pointcut("anyPublicMethodInOzgCloud() && target(de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper)") + void publicMethodInEngineBasedMapper() { + // aspect pointcut - no implementation needed + } +} diff --git a/common/src/main/java/de/ozgcloud/eingang/EingangLoggingAspect.java b/common/src/main/java/de/ozgcloud/eingang/EingangLoggingAspect.java new file mode 100644 index 0000000000000000000000000000000000000000..584acf3a329f1b2e79b62184c861b1b79f1e783c --- /dev/null +++ b/common/src/main/java/de/ozgcloud/eingang/EingangLoggingAspect.java @@ -0,0 +1,25 @@ +package de.ozgcloud.eingang; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +import de.ozgcloud.common.logging.AspectLoggingUtils; + +@Aspect +@Component +public class EingangLoggingAspect extends EingangAspectPointcuts { + + @Before("publicMethodInEngineBasedMapper()") + public void onEngineBasedMapper(JoinPoint joinPoint) { + AspectLoggingUtils.log(joinPoint); + } + + @AfterReturning(pointcut = "publicMethodInEngineBasedMapper()", returning = "returnValue") + public void afterServiceMethod(JoinPoint joinPoint, Object returnValue) { + AspectLoggingUtils.logReturnValue(joinPoint, returnValue); + } + +} diff --git a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java index 3296ccb5e34cf25e47720371c9b32fa7881aeeab..26ff0c888125264f81d9d31ea6c8ba5ae8381384 100644 --- a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java +++ b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormData.java @@ -64,16 +64,21 @@ public class FormData { @Singular private List<IncomingFile> representations; - private FormDataControl control; + @Builder.Default + private FormDataControl control = FormDataControl.builder().build(); @Getter - @Builder + @Builder(toBuilder = true) + @ToString public static class FormDataControl { - private Optional<Representations> representations; + @Builder.Default + private Optional<Representations> representations = Optional.empty(); + @Builder.Default + private Optional<FormMetaData> metaData = Optional.empty(); } @Getter - @Builder + @Builder(toBuilder = true) public static class Representations { private String primaryFormDataRepresentation; private String primaryFormDataPdfRepresentation; diff --git a/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormMetaData.java b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormMetaData.java new file mode 100644 index 0000000000000000000000000000000000000000..c84b8b634ee20fc695a27e194a6ed3bae0554621 --- /dev/null +++ b/common/src/main/java/de/ozgcloud/eingang/common/formdata/FormMetaData.java @@ -0,0 +1,19 @@ +package de.ozgcloud.eingang.common.formdata; + +import java.time.ZonedDateTime; + +public interface FormMetaData { + + ZonedDateTime getOrigin(); + ZonedDateTime getDelivery(); + + /** + * Returns the value of the Entry, or null if this MetaData contains no Entry + * for the name. + * + * @param name Name of the requested Entry + * @return Value of the Entry + */ + String getEntry(String name); + +} diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataControlTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataControlTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..e95c1e0fccf66519d23c26008a3a145bf562a2ff --- /dev/null +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataControlTestFactory.java @@ -0,0 +1,23 @@ +package de.ozgcloud.eingang.common.formdata; + +import java.util.Optional; + +import de.ozgcloud.eingang.common.formdata.FormData.FormDataControl; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; + +public class FormDataControlTestFactory { + + public static String PRIMARY_FORM_DATA_REPRESENTATION = "Antrag.xml"; + + public static FormDataControl create() { + return createBuilder().build(); + } + + public static FormDataControl.FormDataControlBuilder createBuilder() { + return FormDataControl.builder() + .representations(Optional.of(Representations.builder() + .primaryFormDataRepresentation(PRIMARY_FORM_DATA_REPRESENTATION) + .build())) + .metaData(Optional.of(FormMetaDataTestFactory.create())); + } +} diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java index 8d23e2cb03b702eb1fb9fc3869e5eb750f72cd84..52dcddeaf62afa188e0716294bf84d615eb5c945 100644 --- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java @@ -62,6 +62,7 @@ public class FormDataTestFactory { .header(FormHeaderTestFactory.create()) .antragsteller(AntragstellerTestFactory.create()) .zustaendigeStelle(ZustaendigeStelleTestFactory.create()) + .control(FormDataControlTestFactory.create()) .formData(Map.of( SIMPLE_VALUE_KEY, SIMPLE_VALUE, SUBFORM_KEY, SUBFORM_VALUE, diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormMetaDataTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormMetaDataTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..987fef7dde61f9d310b1700c9b927119a6af6105 --- /dev/null +++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormMetaDataTestFactory.java @@ -0,0 +1,36 @@ +package de.ozgcloud.eingang.common.formdata; + +import java.time.ZonedDateTime; + +public class FormMetaDataTestFactory { + + public static final String XTA_IDENTIFIER_ENTRY_NAME = "xtaIdentifier"; + + public static final String XTA_IDENTIFIER = "vbe:010550120100"; + public static final String OE_ID = "010550120100"; + + public static FormMetaData create() { + return new FormMetaData() { + + @Override + public ZonedDateTime getOrigin() { + return ZonedDateTime.now(); + } + + @Override + public ZonedDateTime getDelivery() { + return ZonedDateTime.now(); + } + + @Override + public String getEntry(String name) { + switch (name) { + case XTA_IDENTIFIER_ENTRY_NAME: + return XTA_IDENTIFIER; + } + return null; + } + + }; + } +} diff --git a/enterprise-adapter/pom.xml b/enterprise-adapter/pom.xml index c08136cc31e0159f9329078fbf87198970dd9e6d..00e281f9f923419d7cf6863b94ce5a3fd627c25b 100644 --- a/enterprise-adapter/pom.xml +++ b/enterprise-adapter/pom.xml @@ -87,10 +87,9 @@ <executions> <execution> <id>build-image</id> - <phase> - install</phase> + <phase>install</phase> <goals> - <goal>build-image</goal> + <goal>build-image-no-fork</goal> </goals> </execution> </executions> diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerExtractor.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerExtractor.java deleted file mode 100644 index 5b4d631b42b68e2c6be47dce4e3cc8f5c7b870d2..0000000000000000000000000000000000000000 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/AntragstellerExtractor.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.ozgcloud.eingang.fim; - -import de.ozgcloud.eingang.common.formdata.FormData; - -public interface AntragstellerExtractor { - - default void extractAntragsteller(final FormData.FormDataBuilder builder, final FormData initialFormData) {} -} diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimBasedAdapter.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimBasedAdapter.java index 5849cf8e8f9e1f9ad90bb87fa28ef75ed75d71cd..6a6a8ce22f230439482be03567c495388c3a8915 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimBasedAdapter.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimBasedAdapter.java @@ -1,74 +1,96 @@ package de.ozgcloud.eingang.fim; -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.FormHeader; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; -import lombok.extern.log4j.Log4j2; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.util.Optional; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormData.FormDataControl; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; +import de.ozgcloud.eingang.common.formdata.IncomingFile; +import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter; +import lombok.NonNull; +import lombok.extern.log4j.Log4j2; @Log4j2 @Component public class FimBasedAdapter implements EngineBasedSemantikAdapter { - static final String FIM_FORM_ENGINE_NAME = "FIM"; - - @Autowired - private FimService fimService; - - @Override - public boolean isResponsible(final FormData formData) { - final String formEngineName = formData.getHeader().getFormEngineName(); - return FIM_FORM_ENGINE_NAME.equals(formEngineName); - } - - @Override - public FormData parseFormData(final FormData initialFormData) { - LOG.info("FIM Mapper running to map formData"); - final Optional<String> entryPointOpt = getEntryPoint(initialFormData.getHeader()); - if (entryPointOpt.isEmpty()) { - LOG.error("No entry point found in metadata file for fim data mapping"); - return initialFormData; - } - final Optional<IncomingFile> fileOpt = findFile(initialFormData, entryPointOpt.get()); - if (fileOpt.isEmpty()) { - LOG.error("Entry point file not found for fim data mapping"); - return initialFormData; - } - try { - final Document document = loadDocument(fileOpt.get()); - return fimService.transformDocument(document, initialFormData); - } catch (ParserConfigurationException | SAXException | IOException | FimException e) { - LOG.error("Can't transform document into fim formdata"); - return initialFormData; - } - } - - private Optional<IncomingFile> findFile(final FormData formData, final String name) { - for (IncomingFile file : formData.getRepresentations()) { - if (file.getName().endsWith(name)) { - return Optional.of(file); - } - } - return Optional.empty(); - } - - private Optional<String> getEntryPoint(final FormHeader formHeader) { - // FIXME OZG-5778 sollte über formdata metadaten kommen statt aus dem meta file geparsed zu werden - return Optional.of("Antrag.xml"); - } - - private Document loadDocument(final IncomingFile incomingFile) throws ParserConfigurationException, IOException, SAXException { - final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - return builder.parse(incomingFile.getContentStream()); - } + static final String FIM_FORM_ENGINE_NAME = "FIM"; + + static final String DEFAULT_FORMDATA_REPRESENTATION_NAME = "Antrag.xml"; + + @Autowired + private FimService fimService; + + @Autowired(required = false) + private List<FimEngineBasedMapper> mappers = Collections.emptyList(); + + @Override + public boolean isResponsible(final FormData formData) { + final String formEngineName = formData.getHeader().getFormEngineName(); + return FIM_FORM_ENGINE_NAME.equals(formEngineName); + } + + @Override + public FormData parseFormData(final FormData initialFormData) { + var mapped = useMappers(initialFormData); + LOG.info("FIM Mapper running to map formData"); + + return findFile(initialFormData, getEntryPoint(initialFormData.getControl())) + .map(primaryRepresentation -> doParsing(mapped, primaryRepresentation)) + .orElseGet(() -> { + LOG.error("Entry point file not found for fim data mapping"); + return mapped; + }); + } + + private FormData useMappers(FormData inFormData) { + var processedFormData = inFormData; + + for (var mapper : mappers) { + processedFormData = mapper.parseFormData(processedFormData); + } + + return processedFormData; + } + + private Optional<IncomingFile> findFile(final FormData formData, final String name) { + return formData.getRepresentations().stream() + .filter(file -> file.getName().endsWith(name)) + .findFirst(); + } + + private FormData doParsing(@NonNull FormData formData, @NonNull IncomingFile formDataPrimaryRepresentation) { + try { + return fimService.transformDocument(loadDocument(formDataPrimaryRepresentation), formData); + } catch (ParserConfigurationException | SAXException | IOException | FimException e) { + LOG.error("Can't transform document into fim formdata.", e); + return formData; + } + } + + String getEntryPoint(FormDataControl formDataControl) { + return formDataControl.getRepresentations().map(Representations::getPrimaryFormDataRepresentation) + .orElseGet(() -> { + LOG.error("No entry point found in metadata file for fim data mapping. Trying default."); + return DEFAULT_FORMDATA_REPRESENTATION_NAME; + }); + } + + private Document loadDocument(final IncomingFile incomingFile) throws ParserConfigurationException, IOException, SAXException { + final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + return builder.parse(incomingFile.getContentStream()); + } + } diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java index 58606186dbe3b312b385398a8fbaece81c688c18..1cfa677b6da117cd91fd7c1419ea4b27ab45dbe2 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java @@ -1,9 +1,9 @@ package de.ozgcloud.eingang.fim; -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; -import lombok.extern.log4j.Log4j2; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + import org.apache.commons.lang3.function.TriFunction; import org.springframework.stereotype.Service; import org.w3c.dom.Document; @@ -12,48 +12,47 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; -import java.util.*; +import de.ozgcloud.eingang.common.formdata.FormData; +import lombok.extern.log4j.Log4j2; @Service @Log4j2 class FimDataMapper implements TriFunction<Document, FimScheme, FormData, FormData.FormDataBuilder> { - private static final String LABEL_KEY = "label"; - private static final String VALUE_KEY = "value"; - - @Override - public FormData.FormDataBuilder apply(final Document document, final FimScheme fimScheme, final FormData initialFormData) { - final FormData.FormDataBuilder formDataBuilder = FormData.builder(); - Map<String, Object> data = new LinkedHashMap<>(); - process(document.getDocumentElement(), fimScheme, data, 0); - formDataBuilder.formData(data); - formDataBuilder.attachments(initialFormData.getAttachments()); - formDataBuilder.representations(initialFormData.getRepresentations()); - return formDataBuilder; - } - - private void process(final Element element, final FimScheme fimScheme, final Map<String, Object> data, final int level) { - final NodeList childNodes = element.getChildNodes(); - - LOG.debug(">".repeat(level) + " " + element.getNodeName()); - - for(int i = 0; i < childNodes.getLength();i++) { - final Node child = childNodes.item(i); - if (!(child instanceof Element)) { - continue; - } - if (child.getChildNodes().getLength() == 1 && child.getChildNodes().item(0) instanceof Text textNode) { - insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), textNode.getTextContent()); - } else { - final Map<String, Object> childMap = new LinkedHashMap<>(); - insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), childMap); - process((Element) child, fimScheme, childMap, level + 1); - } - } - } - - private void insertValueIntoFormData(final Map<String, Object> data, final Optional<String> fieldName, final String nodeName, final Object obj) { - final Map<String, Object> labelMap = Map.of(LABEL_KEY, fieldName.orElse(nodeName), VALUE_KEY, obj); - data.put(nodeName, labelMap); - } + private static final String LABEL_KEY = "label"; + private static final String VALUE_KEY = "value"; + + @Override + public FormData.FormDataBuilder apply(final Document document, final FimScheme fimScheme, final FormData initialFormData) { + final FormData.FormDataBuilder formDataBuilder = initialFormData.toBuilder(); + Map<String, Object> data = new LinkedHashMap<>(); + process(document.getDocumentElement(), fimScheme, data, 0); + formDataBuilder.formData(data); + return formDataBuilder; + } + + private void process(final Element element, final FimScheme fimScheme, final Map<String, Object> data, final int level) { + final NodeList childNodes = element.getChildNodes(); + + LOG.debug(">".repeat(level) + " " + element.getNodeName()); + + for (int i = 0; i < childNodes.getLength(); i++) { + final Node child = childNodes.item(i); + if (!(child instanceof Element)) { + continue; + } + if (child.getChildNodes().getLength() == 1 && child.getChildNodes().item(0) instanceof Text textNode) { + insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), textNode.getTextContent()); + } else { + final Map<String, Object> childMap = new LinkedHashMap<>(); + insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), childMap); + process((Element) child, fimScheme, childMap, level + 1); + } + } + } + + private void insertValueIntoFormData(final Map<String, Object> data, final Optional<String> fieldName, final String nodeName, final Object obj) { + final Map<String, Object> labelMap = Map.of(LABEL_KEY, fieldName.orElse(nodeName), VALUE_KEY, obj); + data.put(nodeName, labelMap); + } } diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimEngineBasedMapper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimEngineBasedMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..f01ac99cc7eebb80f297041f7edba27bf91b2c23 --- /dev/null +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimEngineBasedMapper.java @@ -0,0 +1,7 @@ +package de.ozgcloud.eingang.fim; + +import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper; + +public interface FimEngineBasedMapper extends EngineBasedMapper { + +} diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeAdapter.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeAdapter.java index 4166b23656cc1d845ee729fdc86212d6f4efc392..13686294fc251cd9ae95758d2d7b885672dd95ea 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeAdapter.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimSchemeAdapter.java @@ -1,38 +1,39 @@ package de.ozgcloud.eingang.fim; -import lombok.extern.log4j.Log4j2; +import java.util.Map; +import java.util.Optional; + import org.w3c.dom.Element; import org.w3c.dom.NodeList; -import java.util.Map; -import java.util.Optional; +import lombok.extern.log4j.Log4j2; @Log4j2 -public abstract class FimSchemeAdapter implements ZustaendigeStelleExtractor, AntragstellerExtractor { - - public abstract FimSchemeIdentifier forIdentifier(); - - public Optional<String> getFieldName(final Map<String, Element> fieldIndex, final String fieldName) { - final String[] fieldNameParts = fieldName.split(":"); - final String fieldNameWithoutNamespace = fieldNameParts[fieldNameParts.length - 1]; - if (!fieldIndex.containsKey(fieldNameWithoutNamespace)) { - LOG.error("Cannot find Field: " + fieldName); - return Optional.empty(); - } - final Element nodeNameElement = fieldIndex.get(fieldNameWithoutNamespace); - final Optional<String> nodeNameOpt = getNameForElement(nodeNameElement); - return nodeNameOpt.map(this::cleanNodeName); - } - - public Optional<String> getNameForElement(final Element element) { - final NodeList nameTags = element.getElementsByTagName("name"); - if (nameTags.getLength() != 1) { - return Optional.empty(); - } - return Optional.ofNullable(nameTags.item(0).getTextContent()); - } - - public String cleanNodeName(final String s) { - return s.trim(); - } +public abstract class FimSchemeAdapter { + + public abstract FimSchemeIdentifier forIdentifier(); + + public Optional<String> getFieldName(final Map<String, Element> fieldIndex, final String fieldName) { + final String[] fieldNameParts = fieldName.split(":"); + final String fieldNameWithoutNamespace = fieldNameParts[fieldNameParts.length - 1]; + if (!fieldIndex.containsKey(fieldNameWithoutNamespace)) { + LOG.error("Cannot find Field: " + fieldName); + return Optional.empty(); + } + final Element nodeNameElement = fieldIndex.get(fieldNameWithoutNamespace); + final Optional<String> nodeNameOpt = getNameForElement(nodeNameElement); + return nodeNameOpt.map(this::cleanNodeName); + } + + public Optional<String> getNameForElement(final Element element) { + final NodeList nameTags = element.getElementsByTagName("name"); + if (nameTags.getLength() != 1) { + return Optional.empty(); + } + return Optional.ofNullable(nameTags.item(0).getTextContent()); + } + + public String cleanNodeName(final String s) { + return s.trim(); + } } diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java index fd2f21c98c447c62cb574fe02480105198c122ff..f0930a90d3c5d9c4f78be0ac10ccb383e8a85b46 100644 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java @@ -1,106 +1,104 @@ package de.ozgcloud.eingang.fim; -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; -import io.micrometer.common.util.StringUtils; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import jakarta.annotation.PostConstruct; -import lombok.extern.log4j.Log4j2; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import de.ozgcloud.eingang.common.formdata.FormData; +import io.micrometer.common.util.StringUtils; +import lombok.extern.log4j.Log4j2; @Service @Log4j2 public class FimService { - public static final String UNKNOWN_SCHEME_NAME = "unknown"; - - @Autowired - private FimProperties fimProperties; - - @Autowired - private FimDataMapper fimDataMapper; - - @Autowired - private ResourceLoader resourceLoader; - - @Autowired - private final List<FimSchemeAdapter> fimSchemeAdapters = new ArrayList<>(); - - private final FimSchemeCatalogue fimSchemeCatalogue = new FimSchemeCatalogue(); - private final FimSchemeAdapterCatalogue fimSchemeAdapterCatalogue = new FimSchemeAdapterCatalogue(); - - private static final FimSchemeAdapter DEFAULT_FIM_SCHEME_ADAPTER = new FimSchemeAdapter() { - @Override - public FimSchemeIdentifier forIdentifier() { return null; } - }; - - @PostConstruct - private void postConstruct() throws ParserConfigurationException, IOException, SAXException { - for (final FimSchemeAdapter fimSchemeAdapter : fimSchemeAdapters) { - fimSchemeAdapterCatalogue.put(fimSchemeAdapter.forIdentifier(), fimSchemeAdapter); - } - for (final String fimSchemaLocation : fimProperties.getSchemeLocations()) { - final FimScheme fimScheme = loadFimScheme(fimSchemaLocation.trim()); - fimSchemeCatalogue.put(fimScheme.getIdentifier(), fimScheme); - } - final FimScheme unknownScheme = buildUnknownScheme(); - fimSchemeCatalogue.put(unknownScheme.getIdentifier(), unknownScheme); - } - - private FimScheme loadFimScheme(final String path) throws ParserConfigurationException, IOException, SAXException { - LOG.debug("Load FIM schema: " + path); - final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - final Document doc = builder.parse(resourceLoader.getResource("classpath:" + path).getFile()); - final String targetNamespace = doc.getDocumentElement().getAttribute("targetNamespace"); - final FimSchemeIdentifier fimSchemeIdentifier = FimSchemeIdentifier.fromString(targetNamespace); - final FimSchemeAdapter fimSchemeAdapter = fimSchemeAdapterCatalogue.getOrDefault(fimSchemeIdentifier, DEFAULT_FIM_SCHEME_ADAPTER); - return new FimScheme(doc, fimSchemeIdentifier, fimSchemeAdapter); - } - - private FimScheme buildUnknownScheme() throws ParserConfigurationException { - final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); - final FimSchemeIdentifier unknownFimSchemeIdentifier = FimSchemeIdentifier.fromString(UNKNOWN_SCHEME_NAME); - final FimSchemeAdapter fimSchemeAdapter = fimSchemeAdapterCatalogue.get(unknownFimSchemeIdentifier); - return new FimScheme(doc, unknownFimSchemeIdentifier, fimSchemeAdapter); - } - - public FormData transformDocument(final Document document, final FormData initialFormData) { - final String[] tagParts = document.getDocumentElement().getTagName().split(":"); - final String namespacePrefix = tagParts.length < 2 ? "" : (":" + tagParts[0]); - final String schemeName = document.getDocumentElement().getAttribute("xmlns" + namespacePrefix); - if (StringUtils.isEmpty(schemeName)) { - throw new FimException("XML Document does not provide a scheme"); - } - final FimScheme scheme = getSchemeForIdentifier(schemeName); - final FormData.FormDataBuilder builder = fimDataMapper.apply(document, scheme, initialFormData); - - final FimSchemeAdapter adapter = scheme.getSchemeAdapter(); - - builder.header(initialFormData.getHeader()); - - adapter.extractAntragsteller(builder, initialFormData); - - adapter.extractZustaendigeStelle(builder, initialFormData); - - return builder.build(); - } - - FimScheme getSchemeForIdentifier(final String fimSchemaName) { - final FimSchemeIdentifier fimSchemeIdentifier = FimSchemeIdentifier.fromString(fimSchemaName); - final FimScheme fimScheme = fimSchemeCatalogue.get(fimSchemeIdentifier); - if (fimScheme == null) { - LOG.error("Cannot find schema for: " + fimSchemaName); - return fimSchemeCatalogue.get(FimSchemeIdentifier.fromString(UNKNOWN_SCHEME_NAME)); - } - return fimScheme; - } + public static final String UNKNOWN_SCHEME_NAME = "unknown"; + + @Autowired + private FimProperties fimProperties; + + @Autowired + private FimDataMapper fimDataMapper; + + @Autowired + private ResourceLoader resourceLoader; + + @Autowired + private final List<FimSchemeAdapter> fimSchemeAdapters = new ArrayList<>(); + + private final FimSchemeCatalogue fimSchemeCatalogue = new FimSchemeCatalogue(); + private final FimSchemeAdapterCatalogue fimSchemeAdapterCatalogue = new FimSchemeAdapterCatalogue(); + + private static final FimSchemeAdapter DEFAULT_FIM_SCHEME_ADAPTER = new FimSchemeAdapter() { + @Override + public FimSchemeIdentifier forIdentifier() { + return null; + } + }; + + @PostConstruct + private void postConstruct() throws ParserConfigurationException, IOException, SAXException { + for (final FimSchemeAdapter fimSchemeAdapter : fimSchemeAdapters) { + fimSchemeAdapterCatalogue.put(fimSchemeAdapter.forIdentifier(), fimSchemeAdapter); + } + for (final String fimSchemaLocation : fimProperties.getSchemeLocations()) { + final FimScheme fimScheme = loadFimScheme(fimSchemaLocation.trim()); + fimSchemeCatalogue.put(fimScheme.getIdentifier(), fimScheme); + } + final FimScheme unknownScheme = buildUnknownScheme(); + fimSchemeCatalogue.put(unknownScheme.getIdentifier(), unknownScheme); + } + + private FimScheme loadFimScheme(final String path) throws ParserConfigurationException, IOException, SAXException { + LOG.debug("Load FIM schema: " + path); + final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + final Document doc = builder.parse(resourceLoader.getResource("classpath:" + path).getFile()); + final String targetNamespace = doc.getDocumentElement().getAttribute("targetNamespace"); + final FimSchemeIdentifier fimSchemeIdentifier = FimSchemeIdentifier.fromString(targetNamespace); + final FimSchemeAdapter fimSchemeAdapter = fimSchemeAdapterCatalogue.getOrDefault(fimSchemeIdentifier, DEFAULT_FIM_SCHEME_ADAPTER); + return new FimScheme(doc, fimSchemeIdentifier, fimSchemeAdapter); + } + + private FimScheme buildUnknownScheme() throws ParserConfigurationException { + final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + final FimSchemeIdentifier unknownFimSchemeIdentifier = FimSchemeIdentifier.fromString(UNKNOWN_SCHEME_NAME); + final FimSchemeAdapter fimSchemeAdapter = fimSchemeAdapterCatalogue.get(unknownFimSchemeIdentifier); + return new FimScheme(doc, unknownFimSchemeIdentifier, fimSchemeAdapter); + } + + public FormData transformDocument(final Document document, final FormData initialFormData) { + final String[] tagParts = document.getDocumentElement().getTagName().split(":"); + final String namespacePrefix = tagParts.length < 2 ? "" : (":" + tagParts[0]); + final String schemeName = document.getDocumentElement().getAttribute("xmlns" + namespacePrefix); + if (StringUtils.isEmpty(schemeName)) { + throw new FimException("XML Document does not provide a scheme"); + } + final FimScheme scheme = getSchemeForIdentifier(schemeName); + final FormData.FormDataBuilder builder = fimDataMapper.apply(document, scheme, initialFormData); + + builder.header(initialFormData.getHeader()); + + return builder.build(); + } + + FimScheme getSchemeForIdentifier(final String fimSchemaName) { + final FimSchemeIdentifier fimSchemeIdentifier = FimSchemeIdentifier.fromString(fimSchemaName); + final FimScheme fimScheme = fimSchemeCatalogue.get(fimSchemeIdentifier); + if (fimScheme == null) { + LOG.error("Cannot find schema for: " + fimSchemaName); + return fimSchemeCatalogue.get(FimSchemeIdentifier.fromString(UNKNOWN_SCHEME_NAME)); + } + return fimScheme; + } } diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/ZustaendigeStelleExtractor.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/ZustaendigeStelleExtractor.java deleted file mode 100644 index a77d159562ec8bf49d40025ff7b9c96bfc722b6b..0000000000000000000000000000000000000000 --- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/ZustaendigeStelleExtractor.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.ozgcloud.eingang.fim; - -import de.ozgcloud.eingang.common.formdata.FormData; - -public interface ZustaendigeStelleExtractor { - default void extractZustaendigeStelle (final FormData.FormDataBuilder builder, final FormData initialFormData) {} -} diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/ZustaendigeStelleMapper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/ZustaendigeStelleMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..72146cb778999343ef393a5d78365c1801893a0d --- /dev/null +++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/ZustaendigeStelleMapper.java @@ -0,0 +1,44 @@ +package de.ozgcloud.eingang.fim; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.springframework.stereotype.Component; + +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; +import lombok.NonNull; + +@Component +class ZustaendigeStelleMapper implements FimEngineBasedMapper { + + static final String XTA_IDENTIFIER_ENTRY_NAME = "xtaIdentifier"; + + // TODO OZG-7086 umstellen auf FIM Headerdaten + + @Override + public FormData parseFormData(FormData formData) { + return formData.getControl().getMetaData() + .map(metaData -> metaData.getEntry(XTA_IDENTIFIER_ENTRY_NAME)) + .filter(Objects::nonNull) + .map(oeId -> setOrganisationsEinheitId(formData.getZustaendigeStelles(), oeId)) + .map(zustStelle -> formData.toBuilder().zustaendigeStelle(zustStelle).build()) + .orElse(formData); + } + + private ZustaendigeStelle setOrganisationsEinheitId(List<ZustaendigeStelle> stelles, @NonNull String oeid) { + var builder = stelles.isEmpty() ? ZustaendigeStelle.builder() : stelles.getFirst().toBuilder(); + + extractOrganisationsEinheitId(oeid).ifPresent(builder::organisationseinheitenId); + return builder.build(); + } + + Optional<String> extractOrganisationsEinheitId(@NonNull String xtaIdentifier) { + var idx = xtaIdentifier.indexOf(":"); + if (idx < 0) { + return Optional.empty(); + } + return Optional.of(xtaIdentifier.substring(idx + 1)); + } +} diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1a09b6a2ef3428543a3981d71f8aa8d38aaf5235 --- /dev/null +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimBasedAdapterTest.java @@ -0,0 +1,46 @@ +package de.ozgcloud.eingang.fim; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Optional; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; + +import de.ozgcloud.eingang.common.formdata.FormData.Representations; +import de.ozgcloud.eingang.common.formdata.FormDataControlTestFactory; + +class FimBasedAdapterTest { + + @InjectMocks + private FimBasedAdapter adapter; + + @Nested + class TestGetEntryPoint { + + @Test + void shouldReturnPrimaryRepresentation() { + var result = adapter.getEntryPoint(FormDataControlTestFactory.create()); + + assertThat(result).isEqualTo(FormDataControlTestFactory.PRIMARY_FORM_DATA_REPRESENTATION); + } + + @Test + void shouldReturnDefaultOnMissingRepresentations() { + var result = adapter.getEntryPoint(FormDataControlTestFactory.createBuilder().representations(Optional.empty()).build()); + + assertThat(result).isEqualTo(FimBasedAdapter.DEFAULT_FORMDATA_REPRESENTATION_NAME); + } + + @Test + void shouldReturnDefaultOnMissingPrimary() { + var control = FormDataControlTestFactory.createBuilder().representations(Optional.of(Representations.builder().build())).build(); + + var result = adapter.getEntryPoint(control); + + assertThat(result).isEqualTo(FimBasedAdapter.DEFAULT_FORMDATA_REPRESENTATION_NAME); + } + } + +} diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceITCase.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceITCase.java index 886bfbefdf7a56498e408582fb8139cf6d08eb17..d48cd2d4a98d2fa477c3b066b8680b2d25cb3c46 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceITCase.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimServiceITCase.java @@ -1,206 +1,199 @@ package de.ozgcloud.eingang.fim; -import de.ozgcloud.common.test.ITCase; -import de.ozgcloud.eingang.common.formdata.FormData; -import de.ozgcloud.eingang.common.formdata.FormHeader; -import de.ozgcloud.eingang.common.formdata.IncomingFile; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; - -import org.w3c.dom.Document; -import org.xml.sax.SAXException; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import de.ozgcloud.common.test.ITCase; +import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.FormHeader; +import de.ozgcloud.eingang.common.formdata.IncomingFile; @ITCase @ActiveProfiles({ "itcase", "test" }) @ImportAutoConfiguration -@SpringBootTest(classes= FimTestConfig.class) +@SpringBootTest(classes = FimTestConfig.class) public class FimServiceITCase { - @Autowired - private FimService fimService; - - @Autowired - private FimBasedAdapter fimBasedAdapter; - - @Test - void shouldFailOnEmptyScheme() { - assertThatThrownBy(() -> { - final Document document = loadDocument("src/test/resources/test1.xml"); - fimService.transformDocument(document, FormData.builder().build()); - }).isInstanceOf(FimException.class).hasMessage("XML Document does not provide a scheme"); - } - - @Test - void shouldNoFindInvalidScheme() { - final FimScheme scheme = fimService.getSchemeForIdentifier("test"); - - assertThat(FimSchemeIdentifier.fromString("unknown")).isEqualTo(scheme.getIdentifier()); - } - - @Test - void shouldFindVersammlungsScheme() { - final FimScheme scheme = fimService.getSchemeForIdentifier("urn:xoev-de:xfall:standard:fim-s17000652_1.4"); - assertThat(scheme).isNotNull(); - } - - @Test - void shouldFindTest2Scheme() { - final FimScheme scheme = fimService.getSchemeForIdentifier("test2"); - assertThat(scheme).isNotNull(); - } - - @Test - void shouldTransformSimpleDocument() throws ParserConfigurationException, IOException, SAXException { - final Document document = loadDocument("src/test/resources/test2.xml"); - final FormData formData = fimService.transformDocument(document, FormData.builder().build()); - - final Map<String, Object> expected = Map.of( - "xs:fim.S1235", Map.of("label", "Testkey", "value", "Testvalue"), - "xs:fim.S1236", Map.of("label", "xs:fim.S1236", "value", "Testvalue 2") - ); - assertThat(expected).isEqualTo(formData.getFormData()); - } - - @Test - void shouldTransformSimpleDocumentWithoutNamespace() throws ParserConfigurationException, IOException, SAXException { - final Document document = loadDocument("src/test/resources/test3.xml"); - final FormData formData = fimService.transformDocument(document, FormData.builder().build()); - - final Map<String, Object> expected = Map.of( - "fim.S1235", Map.of("label", "Testkey", "value", "Testvalue"), - "fim.S1236", Map.of("label", "fim.S1236", "value", "Testvalue 2") - ); - assertThat(expected).isEqualTo(formData.getFormData()); - } - - @Test - void shouldTransformDocument() throws ParserConfigurationException, IOException, SAXException { - final Document document = loadDocument("src/test/resources/S17000652V1.4_test01.xml"); - FormData formData = fimService.transformDocument(document, FormData.builder().build()); - - assertThat(formData).isNotNull(); - - final Map<String, Object> expected = Map.of( - "xfd:G17003529", Map.of( - "label","EfA|SH Standard", - "value", Map.of( - "xfd:G05001479", Map.of( - "label","nachrichtenkopf", - "value", Map.of( - "xfd:G05001480", Map.of( - "label","identifikation.nachricht", - "value", Map.of( - "xfd:F05002750", Map.of("label", "nachrichtenUUID", "value", "d447e43a-5723-4821-a170-cb44d2dbf143"), - "xfd:F05002751", Map.of("label", "erstellungszeitpunkt", "value", "2022-08-15T09:30:47"), - "xfd:F05002752", Map.of("label", "nachrichtentyp", "value", "fim.S17000652.17000652001004"), - "xfd:F05002753", Map.of("label", "dienstname", "value", "urn:fim:Versammlungsanzeige:1.4") - ) - ), - "xfd:G05001481", Map.of( - "label","Leser", - "value", Map.of( - "xfd:F05002754", Map.of("label", "Organisationsname", "value", "Celle"), - "xfd:F05002755", Map.of("label", "Organisationsschlüssel", "value", "vbe:010550120100"), - "xfd:F05002756", Map.of("label", "Kategorie", "value", "Versammlungsbehörde") - ) - ), - "xfd:G05001482", Map.of( - "label","Autor", - "value", Map.of( - "xfd:F05002754", Map.of("label", "Organisationsname", "value", "OSI-Onlinedienst Niedersachsen Versammlungsanzeige"), - "xfd:F05002755", Map.of("label", "Organisationsschlüssel", "value", "vbe:010550120100"), - "xfd:F05002756", Map.of("label", "Kategorie", "value", "Engagement- und Hobbyportal") - ) - ) - ) - ), - "xfd:F17005454", Map.of("label", "Datenschutzhinweis DSGVO", "value", "true"), - "xfd:F17005455", Map.of("label", "Zustimmung zu einem digitalen Bescheid", "value", "true"), - "xfd:F17005533", Map.of("label", "UUID", "value", "String") - ) - ), - "xfd:F17009191", Map.of("label", "Anzeige durch Person", "value", "true"), - "xfd:F17003371", Map.of("label", "Anzeigenart", "value", "String") - ); - - assertThat(expected).isEqualTo(formData.getFormData()); - } - - @Test - void shouldFallbackUnknownScheme() { - IncomingFile r1 = IncomingFile.builder().name("src/test/resources/test3/Antrag.xml").file(new File("src/test/resources/test3/Antrag.xml")).build(); - IncomingFile r2 = IncomingFile.builder().name("src/test/resources/test3/fim_xtaMetadata.xml").build(); - final FormData initialFormData = FormData.builder() - .header(FormHeader.builder().channel("XTA").formEngineName("FIM").build()) - .representations(List.of(r1, r2)).build(); - - FormData formData = fimBasedAdapter.parseFormData(initialFormData); - - assertThat(formData).isNotNull(); - - final Map<String, Object> expected = Map.of( - "xfd:G17003529", Map.of( - "label","xfd:G17003529", - "value", Map.of( - "xfd:G05001479", Map.of( - "label","xfd:G05001479", - "value", Map.of( - "xfd:G05001480", Map.of( - "label","xfd:G05001480", - "value", Map.of( - "xfd:F05002750", Map.of("label", "xfd:F05002750", "value", "d447e43a-5723-4821-a170-cb44d2dbf143"), - "xfd:F05002751", Map.of("label", "xfd:F05002751", "value", "2022-08-15T09:30:47"), - "xfd:F05002752", Map.of("label", "xfd:F05002752", "value", "fim.S17000652.17000652001004"), - "xfd:F05002753", Map.of("label", "xfd:F05002753", "value", "urn:fim:Versammlungsanzeige:1.4") - ) - ), - "xfd:G05001481", Map.of( - "label","xfd:G05001481", - "value", Map.of( - "xfd:F05002754", Map.of("label", "xfd:F05002754", "value", "Celle"), - "xfd:F05002755", Map.of("label", "xfd:F05002755", "value", "vbe:010550120100"), - "xfd:F05002756", Map.of("label", "xfd:F05002756", "value", "Versammlungsbehörde") - ) - ), - "xfd:G05001482", Map.of( - "label","xfd:G05001482", - "value", Map.of( - "xfd:F05002754", Map.of("label", "xfd:F05002754", "value", "OSI-Onlinedienst Niedersachsen Versammlungsanzeige"), - "xfd:F05002755", Map.of("label", "xfd:F05002755", "value", "vbe:010550120100"), - "xfd:F05002756", Map.of("label", "xfd:F05002756", "value", "Engagement- und Hobbyportal") - ) - ) - ) - ), - "xfd:F17005454", Map.of("label", "xfd:F17005454", "value", "true"), - "xfd:F17005455", Map.of("label", "xfd:F17005455", "value", "true"), - "xfd:F17005533", Map.of("label", "xfd:F17005533", "value", "String") - ) - ), - "xfd:F17009191", Map.of("label", "xfd:F17009191", "value", "true"), - "xfd:F17003371", Map.of("label", "xfd:F17003371", "value", "String") - ); - - assertThat(expected).isEqualTo(formData.getFormData()); - } - - private Document loadDocument(final String path) throws ParserConfigurationException, IOException, SAXException { - final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - return builder.parse(new File(path)); - } + @Autowired + private FimService fimService; + + @Autowired + private FimBasedAdapter fimBasedAdapter; + + @Test + void shouldFailOnEmptyScheme() { + assertThatThrownBy(() -> { + final Document document = loadDocument("src/test/resources/test1.xml"); + fimService.transformDocument(document, FormData.builder().build()); + }).isInstanceOf(FimException.class).hasMessage("XML Document does not provide a scheme"); + } + + @Test + void shouldNoFindInvalidScheme() { + final FimScheme scheme = fimService.getSchemeForIdentifier("test"); + + assertThat(FimSchemeIdentifier.fromString("unknown")).isEqualTo(scheme.getIdentifier()); + } + + @Test + void shouldFindVersammlungsScheme() { + final FimScheme scheme = fimService.getSchemeForIdentifier("urn:xoev-de:xfall:standard:fim-s17000652_1.4"); + assertThat(scheme).isNotNull(); + } + + @Test + void shouldFindTest2Scheme() { + final FimScheme scheme = fimService.getSchemeForIdentifier("test2"); + assertThat(scheme).isNotNull(); + } + + @Test + void shouldTransformSimpleDocument() throws ParserConfigurationException, IOException, SAXException { + final Document document = loadDocument("src/test/resources/test2.xml"); + final FormData formData = fimService.transformDocument(document, FormData.builder().build()); + + final Map<String, Object> expected = Map.of( + "xs:fim.S1235", Map.of("label", "Testkey", "value", "Testvalue"), + "xs:fim.S1236", Map.of("label", "xs:fim.S1236", "value", "Testvalue 2")); + assertThat(expected).isEqualTo(formData.getFormData()); + } + + @Test + void shouldTransformSimpleDocumentWithoutNamespace() throws ParserConfigurationException, IOException, SAXException { + final Document document = loadDocument("src/test/resources/test3.xml"); + final FormData formData = fimService.transformDocument(document, FormData.builder().build()); + + final Map<String, Object> expected = Map.of( + "fim.S1235", Map.of("label", "Testkey", "value", "Testvalue"), + "fim.S1236", Map.of("label", "fim.S1236", "value", "Testvalue 2")); + assertThat(expected).isEqualTo(formData.getFormData()); + } + + @Test + void shouldTransformDocument() throws ParserConfigurationException, IOException, SAXException { + final Document document = loadDocument("src/test/resources/S17000652V1.4_test01.xml"); + FormData formData = fimService.transformDocument(document, FormData.builder().build()); + + assertThat(formData).isNotNull(); + + final Map<String, Object> expected = Map.of( + "xfd:G17003529", Map.of( + "label", "EfA|SH Standard", + "value", Map.of( + "xfd:G05001479", Map.of( + "label", "nachrichtenkopf", + "value", Map.of( + "xfd:G05001480", Map.of( + "label", "identifikation.nachricht", + "value", Map.of( + "xfd:F05002750", + Map.of("label", "nachrichtenUUID", "value", "d447e43a-5723-4821-a170-cb44d2dbf143"), + "xfd:F05002751", + Map.of("label", "erstellungszeitpunkt", "value", "2022-08-15T09:30:47"), + "xfd:F05002752", + Map.of("label", "nachrichtentyp", "value", "fim.S17000652.17000652001004"), + "xfd:F05002753", + Map.of("label", "dienstname", "value", "urn:fim:Versammlungsanzeige:1.4"))), + "xfd:G05001481", Map.of( + "label", "Leser", + "value", Map.of( + "xfd:F05002754", Map.of("label", "Organisationsname", "value", "Celle"), + "xfd:F05002755", + Map.of("label", "Organisationsschlüssel", "value", "vbe:010550120100"), + "xfd:F05002756", Map.of("label", "Kategorie", "value", "Versammlungsbehörde"))), + "xfd:G05001482", Map.of( + "label", "Autor", + "value", Map.of( + "xfd:F05002754", + Map.of("label", "Organisationsname", "value", + "OSI-Onlinedienst Niedersachsen Versammlungsanzeige"), + "xfd:F05002755", + Map.of("label", "Organisationsschlüssel", "value", "vbe:010550120100"), + "xfd:F05002756", + Map.of("label", "Kategorie", "value", "Engagement- und Hobbyportal"))))), + "xfd:F17005454", Map.of("label", "Datenschutzhinweis DSGVO", "value", "true"), + "xfd:F17005455", Map.of("label", "Zustimmung zu einem digitalen Bescheid", "value", "true"), + "xfd:F17005533", Map.of("label", "UUID", "value", "String"))), + "xfd:F17009191", Map.of("label", "Anzeige durch Person", "value", "true"), + "xfd:F17003371", Map.of("label", "Anzeigenart", "value", "String")); + + assertThat(expected).isEqualTo(formData.getFormData()); + } + + @Test + void shouldFallbackUnknownScheme() { + IncomingFile r1 = IncomingFile.builder().name("src/test/resources/test3/Antrag.xml").file(new File("src/test/resources/test3/Antrag.xml")) + .build(); + IncomingFile r2 = IncomingFile.builder().name("src/test/resources/test3/fim_xtaMetadata.xml").build(); + final FormData initialFormData = FormDataTestFactory.createBuilder().formData(null) + .header(FormHeader.builder().channel("XTA").formEngineName("FIM").build()) + .representations(List.of(r1, r2)).build(); + + FormData formData = fimBasedAdapter.parseFormData(initialFormData); + + assertThat(formData).isNotNull(); + + final Map<String, Object> expected = Map.of( + "xfd:G17003529", Map.of( + "label", "xfd:G17003529", + "value", Map.of( + "xfd:G05001479", Map.of( + "label", "xfd:G05001479", + "value", Map.of( + "xfd:G05001480", Map.of( + "label", "xfd:G05001480", + "value", Map.of( + "xfd:F05002750", + Map.of("label", "xfd:F05002750", "value", "d447e43a-5723-4821-a170-cb44d2dbf143"), + "xfd:F05002751", Map.of("label", "xfd:F05002751", "value", "2022-08-15T09:30:47"), + "xfd:F05002752", + Map.of("label", "xfd:F05002752", "value", "fim.S17000652.17000652001004"), + "xfd:F05002753", + Map.of("label", "xfd:F05002753", "value", "urn:fim:Versammlungsanzeige:1.4"))), + "xfd:G05001481", Map.of( + "label", "xfd:G05001481", + "value", Map.of( + "xfd:F05002754", Map.of("label", "xfd:F05002754", "value", "Celle"), + "xfd:F05002755", Map.of("label", "xfd:F05002755", "value", "vbe:010550120100"), + "xfd:F05002756", Map.of("label", "xfd:F05002756", "value", "Versammlungsbehörde"))), + "xfd:G05001482", Map.of( + "label", "xfd:G05001482", + "value", Map.of( + "xfd:F05002754", + Map.of("label", "xfd:F05002754", "value", + "OSI-Onlinedienst Niedersachsen Versammlungsanzeige"), + "xfd:F05002755", Map.of("label", "xfd:F05002755", "value", "vbe:010550120100"), + "xfd:F05002756", + Map.of("label", "xfd:F05002756", "value", "Engagement- und Hobbyportal"))))), + "xfd:F17005454", Map.of("label", "xfd:F17005454", "value", "true"), + "xfd:F17005455", Map.of("label", "xfd:F17005455", "value", "true"), + "xfd:F17005533", Map.of("label", "xfd:F17005533", "value", "String"))), + "xfd:F17009191", Map.of("label", "xfd:F17009191", "value", "true"), + "xfd:F17003371", Map.of("label", "xfd:F17003371", "value", "String")); + + assertThat(formData.getFormData()).usingRecursiveComparison().isEqualTo(expected); + } + + private Document loadDocument(final String path) throws ParserConfigurationException, IOException, SAXException { + final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + return builder.parse(new File(path)); + } } diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimTestConfig.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimTestConfig.java index f0a28ec4b7be509a0de6663720ab2f2964546065..8e88e6f0ae161bffefca00daaef61bb3871a508a 100644 --- a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimTestConfig.java +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimTestConfig.java @@ -6,6 +6,6 @@ import org.springframework.context.annotation.Configuration; @Configuration @EnableAutoConfiguration -@ComponentScan("de.ozgcloud.eingang.fim") +@ComponentScan("de.ozgcloud.eingang") public class FimTestConfig { } diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/ZustaendigeStelleMapperTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/ZustaendigeStelleMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..23fa26757fccee0f45863f256e9f34522ccae81c --- /dev/null +++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/ZustaendigeStelleMapperTest.java @@ -0,0 +1,44 @@ +package de.ozgcloud.eingang.fim; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; + +import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; +import de.ozgcloud.eingang.common.formdata.FormMetaDataTestFactory; +import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; + +class ZustaendigeStelleMapperTest { + + @InjectMocks + private ZustaendigeStelleMapper mapper; + + @Test + void shouldSetOrganisationsEinheitId() { + var parsed = mapper.parseFormData(FormDataTestFactory.createBuilder().clearZustaendigeStelles().build()); + + assertThat(parsed.getZustaendigeStelles()).hasSize(1).first().extracting(ZustaendigeStelle::getOrganisationseinheitenId) + .isEqualTo(FormMetaDataTestFactory.OE_ID); + +// assertThat(parsed.getZustaendigeStelle().getOrganisationseinheitenId()).isEqualTo(FormMetaDataTestFactory.OE_ID); + } + + @Test + void shouldWorkWithoutGivenZustaendigeStelle() { + var parsed = mapper.parseFormData(FormDataTestFactory.createBuilder().clearZustaendigeStelles().build()); + + assertThat(parsed.getZustaendigeStelles()).hasSize(1).first().extracting(ZustaendigeStelle::getOrganisationseinheitenId) + .isNotNull(); + +// assertThat(parsed.getZustaendigeStelle()).isNotNull(); + } + + @Test + void shouldIgnoreMalformedDestinationId() { + var oeid = mapper.extractOrganisationsEinheitId("quatsch"); + + assertThat(oeid).isEmpty(); + } + +} diff --git a/formcycle-adapter/formcycle-adapter-impl/pom.xml b/formcycle-adapter/formcycle-adapter-impl/pom.xml index b436b5b2683398a30e5f350fff013d2ca184e4a3..3d5699205b4bcd63f2c78fe66dfbbda3fe5be060 100644 --- a/formcycle-adapter/formcycle-adapter-impl/pom.xml +++ b/formcycle-adapter/formcycle-adapter-impl/pom.xml @@ -123,7 +123,7 @@ <id>build-image</id> <phase>install</phase> <goals> - <goal>build-image</goal> + <goal>build-image-no-fork</goal> </goals> </execution> </executions> diff --git a/formsolutions-adapter/pom.xml b/formsolutions-adapter/pom.xml index 1e08df0d029b0fbe57ec6363ee8fa303d5ced7cd..61a100c3ea25a117167baf6a2d84014a30d9cac3 100644 --- a/formsolutions-adapter/pom.xml +++ b/formsolutions-adapter/pom.xml @@ -174,27 +174,14 @@ <groupId>pl.project13.maven</groupId> <artifactId>git-commit-id-plugin</artifactId> </plugin> - <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> - <configuration> - <image> - <!-- cann be removed when using common lib > 2.3.2--> - <builder>paketobuildpacks/builder-jammy-base</builder> - <env> - <BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS> - <BPE_APPEND_JAVA_TOOL_OPTIONS>-Dfile.encoding=UTF-8</BPE_APPEND_JAVA_TOOL_OPTIONS> - </env> - </image> - </configuration> - </plugin> - + </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> </plugin> - </plugins> </build> @@ -211,7 +198,7 @@ <id>build-image</id> <phase>install</phase> <goals> - <goal>build-image</goal> + <goal>build-image-no-fork</goal> </goals> </execution> </executions> diff --git a/intelliform-adapter/pom.xml b/intelliform-adapter/pom.xml index 88ed01c34144fe964d07e4d1cef50e290271fbfc..3d8c9820d3501241aa7d069deac51cd92bb3de93 100644 --- a/intelliform-adapter/pom.xml +++ b/intelliform-adapter/pom.xml @@ -244,7 +244,7 @@ <id>build-image</id> <phase>install</phase> <goals> - <goal>build-image</goal> + <goal>build-image-no-fork</goal> </goals> </execution> </executions> diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java index b58584e84b0ccf8362a448a506449d67bc7a23c2..caa77acc9a6d0b07d8d084c96ea7251df1341d96 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java @@ -64,15 +64,13 @@ class FormDataEndpointTest { } private Deposit buildRequest(String fileName) throws SAXException, IOException, ParserConfigurationException, URISyntaxException { - var depositData = new DepositData(); var attachment = new Attachment(); attachment.setName("XML-Daten.xml"); attachment.setContent(TestUtils.loadTextFile(fileName).getBytes()); - depositData.getAttachments() - .add(attachment); + depositData.getAttachments().add(attachment); var deposit = new Deposit(); deposit.setData(depositData); diff --git a/pom.xml b/pom.xml index ef5ca973dfbeaa5d7adbf41ee7d5d324a7bd7287..507bba28c75ff92d74e2dacf54de22bf169913ab 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-parent</artifactId> - <version>4.3.1</version> + <version>4.7.0-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> diff --git a/router/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/router/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 099d759980592d22435720bf65909618aa0d3c2a..0000000000000000000000000000000000000000 --- a/router/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,6 +0,0 @@ -net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration -net.devh.boot.grpc.client.autoconfigure.GrpcClientMetricAutoConfiguration -net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration -net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration -net.devh.boot.grpc.client.autoconfigure.GrpcClientTraceAutoConfiguration -net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration \ No newline at end of file diff --git a/xta-adapter/pom.xml b/xta-adapter/pom.xml index e350593e7679b71e644bd6cb19efef3f2d12c7f7..8c519d2ecfa0697c6d3d6018a97aa4a697dc06a7 100644 --- a/xta-adapter/pom.xml +++ b/xta-adapter/pom.xml @@ -168,6 +168,7 @@ </plugin> </plugins> </build> + <profiles> <profile> <id>ci-build</id> @@ -181,7 +182,7 @@ <id>build-image</id> <phase>install</phase> <goals> - <goal>build-image</goal> + <goal>build-image-no-fork</goal> </goals> </execution> </executions> diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessage.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessage.java index bb048d1c60c284da67062008acfdb6d5b1972281..2f51bd853ba2b95d58481319c083bc20f089c94f 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessage.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessage.java @@ -9,6 +9,8 @@ import lombok.Singular; @Builder(toBuilder = true) @Getter public class XtaMessage { + private String primaryFormDataMessage; + private XtaMessageMetaData metaData; @Singular private Collection<XtaFile> messageFiles; diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java index 09d353faf28d73111a2696cfc89e47978f9d07b4..7fb082ce762666db56da08c5734d9517738ef1a0 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java @@ -1,15 +1,18 @@ package de.ozgcloud.eingang.xta; +import java.util.Optional; + import org.mapstruct.Context; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormHeader; +import de.ozgcloud.eingang.common.formdata.FormMetaData; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper; -@Mapper(imports = {FilesMapperHelper.class, XtaMapperHelper.class}) +@Mapper(imports = { FilesMapperHelper.class, XtaMapperHelper.class }) interface XtaMessageMapper { int VORGANG_NUMMER_SUFFIX_LENGTH = 4; @@ -22,6 +25,7 @@ interface XtaMessageMapper { @Mapping(target = "numberOfRepresentations", dependsOn = "representations", expression = "java(representationsAttachmentsPair.representations().size())") @Mapping(target = "representation", ignore = true) @Mapping(target = "attachment", ignore = true) + @Mapping(target = "control.metaData", source = "metaData") FormData toFormData(RepresentationsAttachmentsPair representationsAttachmentsPair, XtaMessageMetaData metaData, @Context VorgangNummerSupplier vorgangNummerSupplier); @@ -39,4 +43,8 @@ interface XtaMessageMapper { default String fromId(XtaMessageId id) { return id.toString(); } + + default Optional<FormMetaData> mapMetaData(XtaMessageMetaData value) { + return Optional.ofNullable(value); + } } diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java index 66d4ed8d011521b3895e738a3eaf7d91b35af8fa..84fc3290bd1420e24750706a3a073cca4801ea2a 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java @@ -2,19 +2,58 @@ package de.ozgcloud.eingang.xta; import java.time.ZonedDateTime; +import de.ozgcloud.eingang.common.formdata.FormMetaData; +import de.ozgcloud.eingang.common.formdata.IncomingFile; import lombok.Builder; import lombok.Getter; +import lombok.ToString; @Builder @Getter -class XtaMessageMetaData { +@ToString +class XtaMessageMetaData implements FormMetaData { + static final String SERVICE = "service"; + static final String MESSAGE_TYPE_ENTRY_NAME = "messageType"; + static final String MESSAGE_TYPE_LIST_VERSION = "messageTypeListVersion"; + static final String MESSAGE_ID_ENTRY_NAME = "messageId"; + static final String XTA_IDENTIFIER_ENTRY_NAME = "xtaIdentifier"; + // MsgIdentification.MessageId private XtaMessageId messageId; + // DeliveryAttributes.origin private ZonedDateTime origin; // DeliveryAttributes.delivery private ZonedDateTime delivery; + // Qualifier.MessageType.code private String messageType; + // Qualifier.MessageType.listVersion + private String messageTypeListVersion; + // Qualifier.Service + private String service; + + private String xtaIdentifier; + + private IncomingFile metaDataFile; + + @Override + public String getEntry(String name) { + switch (name) { + case MESSAGE_TYPE_ENTRY_NAME: + return getMessageType(); + case MESSAGE_TYPE_LIST_VERSION: + return getMessageTypeListVersion(); + case MESSAGE_ID_ENTRY_NAME: + return getMessageId().toString(); + case XTA_IDENTIFIER_ENTRY_NAME: + return getXtaIdentifier(); + case SERVICE: + return getService(); + + default: + return null; + } + } } diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java index 2cb772154e77246a41508a0116dd6db7f9cf9cae..f5566e157a78701db29b3ca828e1e9e8fdcb5cef 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapper.java @@ -13,10 +13,14 @@ import eu.osci.ws._2014._10.transport.MessageMetaData; @Mapper interface XtaMessageMetaDataMapper { + @Mapping(target = "messageTypeListVersion", ignore = true) + @Mapping(target = "metaDataFile", ignore = true) + @Mapping(target = "service", ignore = true) @Mapping(target = "origin", source = "deliveryAttributes.origin") @Mapping(target = "delivery", source = "deliveryAttributes.delivery") @Mapping(target = "messageId", source = "msgIdentification.messageID.value") @Mapping(target = "messageType", source = "qualifier.messageType.code") + @Mapping(target = "xtaIdentifier", source = "destinations.reader.identifier.value") XtaMessageMetaData fromSoap(MessageMetaData metaData); default XtaMessageId fromString(String id) { diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java index c1d3ecfb782a7e0f42f2feab9cadb78b621ff15c..a837c55d3c1670242f12ea891542be116052e09f 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaRemoteService.java @@ -94,7 +94,6 @@ class XtaRemoteService { } MsgStatusListTypeAndHeaderResponse getGenericStatusList(Object request) { - var template = webServiceTemplateBuilder.setMarshaller(osciMarshaller).setUnmarshaller(osciMarshaller).build(); return template.sendAndReceive(buildMarshalCallBack(request, buildActionCallback()), buildHeaderExtractor()); @@ -183,10 +182,12 @@ class XtaRemoteService { public XtaMessage getMessage(XtaMessageId messageId) { var contentContainer = loadContentContainer(messageId.toString()); + XtaFile formDataFile = getMessage(contentContainer); return XtaMessage.builder() .metaData(null) - .messageFiles(Collections.singleton(getMessage(contentContainer))) + .primaryFormDataMessage(formDataFile.name()) + .messageFiles(Collections.singleton(formDataFile)) .attachments(getAttachments(contentContainer).toList()) .build(); } diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java index f8643d2fb5221c5e3585e4436c757a015cb7d3ee..500e78da873a6acfc55c01a880f4ec953a875d4a 100644 --- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java +++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Service; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.common.formdata.IncomingFileGroup; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; @@ -85,7 +86,23 @@ class XtaService { var representationsAttachmentsPair = getRepresentationsAttachmentsPair(metaData, incomingFiles); var formData = mapper.toFormData(representationsAttachmentsPair, metaData, vorgangNummerSupplier); - return addAttachments(msg, formData); + formData = addAttachments(msg, formData); + + return addRepresentations(formData, msg); + } + + FormData addRepresentations(FormData formData, XtaMessage msg) { + return formData.toBuilder().control( + formData.getControl().toBuilder() + .representations(Optional.of(buildRepresentations(formData.getControl().getRepresentations(), msg))) + .build()) + .build(); + } + + private Representations buildRepresentations(Optional<Representations> base, XtaMessage msg) { + return base.map(Representations::toBuilder).orElseGet(Representations::builder) + .primaryFormDataRepresentation(msg.getPrimaryFormDataMessage()) + .build(); } FormData addAttachments(XtaMessage msg, FormData inFormData) { diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java index 83d1dc8f4fee83ad384db085315e9fbcc37cd075..23a2f984e0b91d38e35e63c3d2d73efd8cd69733 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java @@ -13,6 +13,7 @@ import org.mockito.Mock; import org.mockito.Spy; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormMetaDataTestFactory; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; class XtaMessageMapperTest { @@ -86,6 +87,14 @@ class XtaMessageMapperTest { assertThat(formData.getHeader().getFormEngineName()).isEqualTo(FormHeaderTestFactory.XDOMEA_FORM_ENGINE_NAME); } + @Test + void shouldSetDesinationId() { + var formData = doMapping(); + + assertThat(formData.getControl().getMetaData()).isPresent().get() + .extracting(metaData -> metaData.getEntry(XtaMessageMetaData.XTA_IDENTIFIER_ENTRY_NAME)) + .isEqualTo(FormMetaDataTestFactory.XTA_IDENTIFIER); + } private FormData doMapping() { return mapper.toFormData(representationsAttachmentsPair, xtaMessageMetaData, vorgangNummerSupplier); @@ -95,7 +104,6 @@ class XtaMessageMapperTest { @Nested class TestToFimFormData { - private XtaMessageMetaData xtaMessageMetaData; private RepresentationsAttachmentsPair representationsAttachmentsPair; @@ -108,7 +116,7 @@ class XtaMessageMapperTest { @Test void shouldSetFormEngineName() { - var formData = mapper.toFormData(representationsAttachmentsPair, xtaMessageMetaData, vorgangNummerSupplier); + var formData = mapper.toFormData(representationsAttachmentsPair, xtaMessageMetaData, vorgangNummerSupplier); assertThat(formData.getHeader().getFormEngineName()).isEqualTo(FormHeaderTestFactory.FIM_FORM_ENGINE_NAME); } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java index 26f1ef8d1c76ea3a17eb9b6031c3df7d5d1e54d9..1233e71346ca304904f22fb36108bae6731bb3d1 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataMapperTest.java @@ -2,8 +2,6 @@ package de.ozgcloud.eingang.xta; import static org.assertj.core.api.Assertions.*; -import java.math.BigInteger; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -21,7 +19,7 @@ class XtaMessageMetaDataMapperTest { @Test void shouldMap() { - var response = MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().build(); + var response = MsgStatusListTypeAndHeaderResponseTestFactory.create(); var result = mapper.msgStatusListFromSoap(response); @@ -31,7 +29,7 @@ class XtaMessageMetaDataMapperTest { @DisplayName("should set moreMessagesAvailable to false") @Test void shouldSetMoreMessagesAvailableToFalse() { - var response = MsgStatusListTypeAndHeaderResponseTestFactory.createBuilder().build(); + var response = MsgStatusListTypeAndHeaderResponseTestFactory.create(); var result = mapper.msgStatusListFromSoap(response); diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java index fbe07498eb8d3435d1c739a268ace2273bc133ac..5ee03139664cf766ba09ac8adc3e95d59e2fc246 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java @@ -4,11 +4,15 @@ import static de.ozgcloud.eingang.xta.XtaMessageTestFactory.*; import java.time.ZonedDateTime; +import de.ozgcloud.eingang.common.formdata.FormMetaDataTestFactory; + class XtaMessageMetaDataTestFactory { static final String MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201"; static final String FIM_MESSAGE_TYPE = "fim.S17000652.17000652001004"; static final ZonedDateTime ORIGIN = ZonedDateTime.parse("2022-10-29T15:45:52.4942149+02:00"); + static final String SERVICE = "urn:fim:Versammlungsanzeige:1.4"; + static final String MESSAGE_TYPE_LIST_VERSION = "1.0"; static XtaMessageMetaData create() { return createBuilder().build(); @@ -18,7 +22,10 @@ class XtaMessageMetaDataTestFactory { return XtaMessageMetaData.builder() .messageId(MESSAGE_ID) .messageType(MESSAGE_TYPE) - .origin(ORIGIN); + .messageTypeListVersion(MESSAGE_TYPE_LIST_VERSION) + .origin(ORIGIN) + .xtaIdentifier(FormMetaDataTestFactory.XTA_IDENTIFIER) + .service(SERVICE); } static XtaMessageMetaData createFim() { @@ -26,9 +33,7 @@ class XtaMessageMetaDataTestFactory { } static XtaMessageMetaData.XtaMessageMetaDataBuilder createFimBuilder() { - return XtaMessageMetaData.builder() - .messageId(MESSAGE_ID) - .messageType(FIM_MESSAGE_TYPE) - .origin(ORIGIN); + return createBuilder() + .messageType(FIM_MESSAGE_TYPE); } } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageTestFactory.java index 6c8597cc38fd795a311ad8d3a70e64a5c24c6347..1a1397db1e1bae3588ef81e7162f8c80308b2283 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageTestFactory.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageTestFactory.java @@ -5,6 +5,7 @@ class XtaMessageTestFactory { static final XtaMessageId MESSAGE_ID = XtaMessageId.from("urn:de:xta:messageid:dataport_xta_210:81e40808-91c6-4765-aaf4-1aa62fec8be9"); static final XtaFile attachment = XtaFileTestFactory.create(); + static final String PRIMARY_FORM_DATA_MESSAGE = XtaFileTestFactory.NAME; static XtaMessage create() { return createBuilder().build(); @@ -14,6 +15,7 @@ class XtaMessageTestFactory { return XtaMessage.builder() .metaData(XtaMessageMetaDataTestFactory.create()) .messageFile(XtaFileTestFactory.create()) + .primaryFormDataMessage(XtaFileTestFactory.NAME) .attachment(attachment); } } diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceFunctionalCase.java similarity index 100% rename from xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java rename to xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceFunctionalCase.java diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java index 2d73c58212d230db5235b25e502bbb7f5ab08949..effc877a5d5045273819eef3e441eb6893da1f02 100644 --- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java +++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java @@ -21,6 +21,8 @@ import org.mockito.Spy; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; +import de.ozgcloud.eingang.common.formdata.FormData.Representations; +import de.ozgcloud.eingang.common.formdata.FormDataControlTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; @@ -281,7 +283,7 @@ class XtaServiceTest { @Test void shouldReturnMappedResult() { - doReturn(mappedFormData).when(service).addAttachments(any(), any()); + doReturn(mappedFormData).when(service).addRepresentations(any(), any()); var result = service.getFormData(messageMetaData); @@ -442,4 +444,28 @@ class XtaServiceTest { } } + @Nested + class TestAddRepresentations { + @Test + void shouldAddPrimaryRepresentation() { + var result = service.addRepresentations(FormDataTestFactory.create(), XtaMessageTestFactory.create()); + + assertThat(result.getControl().getRepresentations()).isPresent().get() + .extracting(Representations::getPrimaryFormDataRepresentation).isEqualTo(XtaMessageTestFactory.PRIMARY_FORM_DATA_MESSAGE); + } + + @Test + void shouldRespectExistingRepresentation() { + var formData = FormDataTestFactory.createBuilder().control(FormDataControlTestFactory.createBuilder() + .representations(Optional.of( + Representations.builder().primaryFormDataPdfRepresentation("PDF_FILE").build())) + .build()).build(); + + var result = service.addRepresentations(formData, XtaMessageTestFactory.create()); + + var baseAssert = assertThat(result.getControl().getRepresentations()).isPresent().get(); + baseAssert.extracting(Representations::getPrimaryFormDataRepresentation).isEqualTo(XtaMessageTestFactory.PRIMARY_FORM_DATA_MESSAGE); + baseAssert.extracting(Representations::getPrimaryFormDataPdfRepresentation).isEqualTo("PDF_FILE"); + } + } }