diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java index 15999aefcb8a5542fb96f1826dd27b9123288307..b12dfc7a99548a5868891da6608dab10242e64d2 100644 --- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java +++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java @@ -23,6 +23,8 @@ */ package de.ozgcloud.eingang.intelliform; +import static java.util.stream.Collectors.*; + import java.io.IOException; import java.util.Collection; import java.util.LinkedHashMap; @@ -71,14 +73,20 @@ class DepositDataMapper { public FormData mapToFormData(DepositData depositData) { Map<String, IncomingFile> incomingFileMap = mapDepositAttachmentsToIncomingFiles(depositData); Document document = parsePrimaryXmlRepresentation(depositData, incomingFileMap); - List<String> attachmentFileIds = findAttachmentFileIds(document); + var attachmentGroups = findAttachmentGroups(document); return mapToFormDataWithRepresentationsAndAttachments( - getRepresentations(incomingFileMap, attachmentFileIds), - getAttachmentFileGroups(attachmentFileIds, incomingFileMap) + getRepresentations(incomingFileMap, getAttachmentFileIds(attachmentGroups)), + getAttachmentFileGroups(attachmentGroups, incomingFileMap) ); } + private List<String> getAttachmentFileIds(Map<String, List<String>> attachmentGroups) { + return attachmentGroups.values().stream() + .flatMap(Collection::stream) + .toList(); + } + private FormData mapToFormDataWithRepresentationsAndAttachments( List<IncomingFile> representations, List<IncomingFileGroup> attachments @@ -128,16 +136,21 @@ class DepositDataMapper { } } - private List<String> findAttachmentFileIds(Document document) { + Map<String, List<String>> findAttachmentGroups(Document document) { return streamElements(document.getElementsByTagName("file")) - .map(element -> element.getAttribute("id")) - .toList(); + .collect(groupingBy( + element -> element.getParentNode().getNodeName(), + mapping( + element -> element.getAttribute("id"), + toList()))); } - private List<IncomingFileGroup> getAttachmentFileGroups(List<String> attachmentFileIds, Map<String, IncomingFile> incomingFileMap) { - return attachmentFileIds.stream() - .map(id -> getIncomingFileById(id, incomingFileMap)) - .map(this::createSingularFileGroup) + private List<IncomingFileGroup> getAttachmentFileGroups(Map<String, List<String>> attachmentGroups, Map<String, IncomingFile> incomingFileMap) { + return attachmentGroups.entrySet().stream() + .map(entry -> IncomingFileGroup.builder() + .name(entry.getKey()) + .files(entry.getValue().stream().map(id -> getIncomingFileById(id, incomingFileMap)).toList()) + .build()) .toList(); } @@ -149,18 +162,11 @@ class DepositDataMapper { private IncomingFile getIncomingFileById(String id, Map<String, IncomingFile> incomingFileMap) { if (!incomingFileMap.containsKey(id)) { - throw new TechnicalException("Failed to find deposit data attachment by id '%s'!".formatted(id)); + throw new TechnicalException("Failed to find <file> attachment ID '%s' in deposit data!".formatted(id)); } return incomingFileMap.get(id); } - IncomingFileGroup createSingularFileGroup(IncomingFile incomingFile) { - return IncomingFileGroup.builder() - .name(incomingFile.getName()) - .file(incomingFile) - .build(); - } - private List<String> getNamesWithout(Collection<String> names, Collection<String> excludedStrings) { var excludedStringsSet = Set.copyOf(excludedStrings); return names.stream().filter(name -> !excludedStringsSet.contains(name)).toList(); @@ -171,4 +177,5 @@ class DepositDataMapper { .mapToObj(nodeList::item) .map(Element.class::cast); } + } diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java index 5249212400e77f7a6a1b2c3913d185363fc441be..c9fdccc9def685a78b48a783d0f391c530ed7408 100644 --- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java +++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java @@ -28,10 +28,15 @@ import static de.ozgcloud.eingang.intelliform.DepositDataTestFactory.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.io.IOException; +import java.io.StringReader; import java.nio.charset.Charset; import java.util.Collections; import java.util.List; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -39,8 +44,10 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; -import org.mockito.Mock; import org.mockito.Spy; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; @@ -231,28 +238,59 @@ class DepositDataMapperTest { } } - @DisplayName("create singular file group") + @DisplayName("find attachment groups") @Nested - class TestCreateSingularFileGroup { - @Mock - IncomingFile incomingFile; + class TestFindAttachmentGroups { - @DisplayName("should have name") + private Document document; + + @BeforeEach + void mock() { + document = buildXMLDocument(""" + <myForm t:client-id="land"> + <Upload1> + <file content-type="image/png" description="" id="VendorId3333" length="155251">Image.png</file> + </Upload1> + <Upload2> + <file id="VendorId1111">name1.txt</file> + <file id="VendorId2222">name2.txt</file> + </Upload2> + <file id="VendorIdxxxx">namex.txt</file> + </myForm>"""); + } + + @DisplayName("should have groups with parent element name") @Test - void shouldHaveName() { - when(incomingFile.getName()).thenReturn("somename"); + void shouldHaveGroupsWithParentElementName() { + var attachmentGroups = mapper.findAttachmentGroups(document); + + assertThat(attachmentGroups).containsOnlyKeys("Upload1", "Upload2", "myForm"); + } - var fileGroup = mapper.createSingularFileGroup(incomingFile); + @DisplayName("should have Upload1 group with fileId") + @Test + void shouldHaveUpload1GroupWithFileId() { + var attachmentGroups = mapper.findAttachmentGroups(document); - assertThat(fileGroup.getName()).isEqualTo(incomingFile.getName()); + assertThat(attachmentGroups.get("Upload1")).containsExactly("VendorId3333"); } - @DisplayName("should have file") + @DisplayName("should have two fileIds in Upload2 group") @Test - void shouldHaveFile() { - var fileGroup = mapper.createSingularFileGroup(incomingFile); + void shouldHaveTwoFileIdsInUpload2Group() { + var attachmentGroups = mapper.findAttachmentGroups(document); + + assertThat(attachmentGroups.get("Upload2")).containsExactly("VendorId1111", "VendorId2222"); + } + } - assertThat(fileGroup.getFiles()).containsExactly(incomingFile); + private Document buildXMLDocument(String xmlString) { + try { + return DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(new InputSource(new StringReader(xmlString))); + } catch (ParserConfigurationException | IOException | SAXException e) { + throw new RuntimeException(e); } }