diff --git a/common/src/main/java/de/ozgcloud/eingang/common/xml/XMLHelper.java b/common/src/main/java/de/ozgcloud/eingang/common/xml/XMLHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..c94b0ae5cc80b81378f6013bb6601bca7835cd65
--- /dev/null
+++ b/common/src/main/java/de/ozgcloud/eingang/common/xml/XMLHelper.java
@@ -0,0 +1,64 @@
+package de.ozgcloud.eingang.common.xml;
+
+import java.io.IOException;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFactoryConfigurationException;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+
+public class XMLHelper {
+
+	private XMLHelper() {
+	}
+
+	private static final DocumentBuilder DOCUMENT_BUILDER = createDocumentBuilder();
+
+	private static DocumentBuilder createDocumentBuilder() {
+		var documentBuilderFactory = DocumentBuilderFactory.newInstance();
+		try {
+			documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+			return documentBuilderFactory.newDocumentBuilder();
+		} catch (ParserConfigurationException e) {
+			throw new TechnicalException("Failed to configure document builder", e);
+		}
+	}
+
+	private static final XPathFactory X_PATH_FACTORY = createXPathFactory();
+
+	private static XPathFactory createXPathFactory() {
+		var xPathFactory = XPathFactory.newInstance();
+		try {
+			xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+			return xPathFactory;
+		} catch (XPathFactoryConfigurationException e) {
+			throw new TechnicalException("Failed to configure xpath factory!", e);
+		}
+	}
+
+	public static Document parseDocument(IncomingFile incomingFile) {
+		try (var inputStream = incomingFile.getContentStream()) {
+			return DOCUMENT_BUILDER.parse(inputStream);
+		} catch (SAXException | IOException e) {
+			throw new TechnicalException("Failed to parse xml document!", e);
+		}
+	}
+
+	public static XPathExpression compileXPathExpression(String xPathString) {
+		try {
+			return X_PATH_FACTORY.newXPath().compile(xPathString);
+		} catch (XPathExpressionException e) {
+			throw new TechnicalException("Failed to compile xpath expression!", e);
+		}
+	}
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ReadZipException.java b/common/src/main/java/de/ozgcloud/eingang/common/zip/ReadZipException.java
similarity index 82%
rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ReadZipException.java
rename to common/src/main/java/de/ozgcloud/eingang/common/zip/ReadZipException.java
index c3fcc85a910df48282884211d68617f4095248df..2a50bc6bc844a3d0a3f2aec157d1e93f1004f338 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ReadZipException.java
+++ b/common/src/main/java/de/ozgcloud/eingang/common/zip/ReadZipException.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.semantik.common;
+package de.ozgcloud.eingang.common.zip;
 
 public class ReadZipException extends RuntimeException {
 
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReader.java b/common/src/main/java/de/ozgcloud/eingang/common/zip/ZipAttachmentReader.java
similarity index 99%
rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReader.java
rename to common/src/main/java/de/ozgcloud/eingang/common/zip/ZipAttachmentReader.java
index 02b4e95012b0343aa44ebd79f6f0305135ad9234..8f060cb8fa68e7045e788920dc9d5e6364fed2c1 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReader.java
+++ b/common/src/main/java/de/ozgcloud/eingang/common/zip/ZipAttachmentReader.java
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.eingang.semantik.common;
+package de.ozgcloud.eingang.common.zip;
 
 import java.io.File;
 import java.io.FileInputStream;
diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java
index 40e803fe1c1a89f4937d00453d574ebb09df7c67..b8f2a5b22249707ee116edde4751a442efe2acdd 100644
--- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java
+++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/IncomingFileTestFactory.java
@@ -65,4 +65,8 @@ public class IncomingFileTestFactory {
 	public static MockMultipartFile asMultipartFile(String multipartName, IncomingFile file) {
 		return new MockMultipartFile(multipartName, file.getName(), file.getContentType(), file.getContentStream().readAllBytes());
 	}
+
+	public static IncomingFile createWithName(String name) {
+		return createBuilder().name(name).build();
+	}
 }
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java b/common/src/test/java/de/ozgcloud/eingang/common/zip/ZipAttachmentReaderTest.java
similarity index 95%
rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java
rename to common/src/test/java/de/ozgcloud/eingang/common/zip/ZipAttachmentReaderTest.java
index f6e1fa7e07c716a5b00a059ea8e46c1c35d16116..8cd2ad76c5b602b4b4e9096211afca5621c8569b 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java
+++ b/common/src/test/java/de/ozgcloud/eingang/common/zip/ZipAttachmentReaderTest.java
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.eingang.semantik.common;
+package de.ozgcloud.eingang.common.zip;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
@@ -47,8 +47,6 @@ import org.springframework.util.MimeTypeUtils;
 
 import de.ozgcloud.common.test.TestUtils;
 import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.semantik.common.ReadZipException;
-import de.ozgcloud.eingang.semantik.common.ZipAttachmentReader;
 import lombok.SneakyThrows;
 
 class ZipAttachmentReaderTest {
@@ -96,7 +94,7 @@ class ZipAttachmentReaderTest {
 		void shouldFailSilentByEncryptedZip() {
 			var zipAttachment = createZipAttachment(ZIP_ENCRYPTED);
 
-			assertThrows(ReadZipException.class, () -> zipAttachment.readContent());
+			assertThrows(ReadZipException.class, zipAttachment::readContent);
 		}
 
 		private static ZipAttachmentReader createZipAttachment(String fileName) {
@@ -115,9 +113,9 @@ class ZipAttachmentReaderTest {
 
 		private static Pair<String, Long> createContentPair(String fileName) {
 			var size = switch (fileName) {
-			case content_file_0_name -> content_file_0_size;
-			case content_file_1_name -> content_file_1_size;
-			default -> getFileSize(fileName);
+				case content_file_0_name -> content_file_0_size;
+				case content_file_1_name -> content_file_1_size;
+				default -> getFileSize(fileName);
 			};
 			return Pair.of(fileName, size);
 		}
@@ -189,7 +187,7 @@ class ZipAttachmentReaderTest {
 
 			var zipAttachment = ZipAttachmentReader.from(invalidZip, "invalid");
 
-			assertThrows(ReadZipException.class, () -> zipAttachment.readContent());
+			assertThrows(ReadZipException.class, zipAttachment::readContent);
 		}
 
 		@Test
diff --git a/semantik-adapter/src/test/resources/attachment-1file.zip b/common/src/test/resources/attachment-1file.zip
similarity index 100%
rename from semantik-adapter/src/test/resources/attachment-1file.zip
rename to common/src/test/resources/attachment-1file.zip
diff --git a/semantik-adapter/src/test/resources/attachment-2files.zip b/common/src/test/resources/attachment-2files.zip
similarity index 100%
rename from semantik-adapter/src/test/resources/attachment-2files.zip
rename to common/src/test/resources/attachment-2files.zip
diff --git a/semantik-adapter/src/test/resources/attachment-empty.zip b/common/src/test/resources/attachment-empty.zip
similarity index 100%
rename from semantik-adapter/src/test/resources/attachment-empty.zip
rename to common/src/test/resources/attachment-empty.zip
diff --git a/semantik-adapter/src/test/resources/attachment-encrypted.zip b/common/src/test/resources/attachment-encrypted.zip
similarity index 100%
rename from semantik-adapter/src/test/resources/attachment-encrypted.zip
rename to common/src/test/resources/attachment-encrypted.zip
diff --git a/semantik-adapter/src/test/resources/zip-file-0.txt b/common/src/test/resources/zip-file-0.txt
similarity index 100%
rename from semantik-adapter/src/test/resources/zip-file-0.txt
rename to common/src/test/resources/zip-file-0.txt
diff --git a/semantik-adapter/src/test/resources/zip-file-1.txt b/common/src/test/resources/zip-file-1.txt
similarity index 100%
rename from semantik-adapter/src/test/resources/zip-file-1.txt
rename to common/src/test/resources/zip-file-1.txt
diff --git a/semantik-adapter/src/test/resources/zipbombs/filewithmanyfiles.dat.zip b/common/src/test/resources/zipbombs/filewithmanyfiles.dat.zip
similarity index 100%
rename from semantik-adapter/src/test/resources/zipbombs/filewithmanyfiles.dat.zip
rename to common/src/test/resources/zipbombs/filewithmanyfiles.dat.zip
diff --git a/semantik-adapter/src/test/resources/zipbombs/filewithnulls.dat.zip b/common/src/test/resources/zipbombs/filewithnulls.dat.zip
similarity index 100%
rename from semantik-adapter/src/test/resources/zipbombs/filewithnulls.dat.zip
rename to common/src/test/resources/zipbombs/filewithnulls.dat.zip
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdder.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdder.java
deleted file mode 100644
index 9bf4387c8ed466c54cf64b09d9f800e7346b0d9f..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-
-@Component
-public class AttachmentsContentAdder {
-
-	public List<IncomingFileGroup> addContentToAttachments(List<IncomingFileGroup> formDataFileGroups, List<IncomingFile> depositRequestFiles) {
-		var fileGroups = new ArrayList<IncomingFileGroup>(formDataFileGroups.size());
-		for (IncomingFileGroup fileGroup : formDataFileGroups) {
-			var files = fileGroup.getFiles().stream()
-					.map(file -> file.toBuilder().file(getContentStreamFromDepositRequest(file.getVendorId(), depositRequestFiles)).build())
-					.toList();
-			fileGroups.add(fileGroup.toBuilder().clearFiles().files(files).build());
-		}
-		return Collections.unmodifiableList(fileGroups);
-	}
-
-	private File getContentStreamFromDepositRequest(String attachmentVendorId, List<IncomingFile> depositRequestFiles) {
-
-		return depositRequestFiles.stream()
-				.filter(depositFile -> depositFile.getVendorId().equals(attachmentVendorId))
-				.map(IncomingFile::getFile)
-				.findFirst()
-				.orElseThrow(() -> new RuntimeException(
-						"DepositFiles does not contain content for attachment with vendorId: " + attachmentVendorId));
-	}
-}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/CustomHeaderReader.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/CustomHeaderReader.java
deleted file mode 100644
index dad25e9f009aa064cc79e5837ccf4687d0dcdc89..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/CustomHeaderReader.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Consumer;
-
-import org.springframework.stereotype.Component;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-
-@Component
-public class CustomHeaderReader {
-
-	public static final String HEADER_POSTFACH_ID = "u:saml_legacypostkorbhandle";
-	public static final String HEADER_VORNAME = "u:saml_givenname";
-	public static final String HEADER_NACHNAME = "u:saml_surname";
-	public static final String HEADER_GEBURTSORT = "u:saml_placeofbirth";
-	public static final String HEADER_GEBURTSNAME = "u:saml_birthname";
-	public static final String HEADER_EMAIL = "u:saml_mail";
-	public static final String HEADER_TELEFON = "u:saml_telephonenumber";
-	public static final String HEADER_STRASSE = "u:saml_postaladdress";
-	public static final String HEADER_PLZ = "u:saml_postalcode";
-	public static final String HEADER_ORT = "u:saml_localityname";
-
-	public Map<String, Object> getHeader(Document document) {
-		var map = new HashMap<String, Object>();
-		Consumer<Attr> addHeader = attr -> map.put(attr.getName(), attr.getValue());
-		getAttribute(document, HEADER_POSTFACH_ID).ifPresent(addHeader);
-		getAttribute(document, HEADER_VORNAME).ifPresent(addHeader);
-		getAttribute(document, HEADER_NACHNAME).ifPresent(addHeader);
-		getAttribute(document, HEADER_GEBURTSNAME).ifPresent(addHeader);
-		getAttribute(document, HEADER_GEBURTSORT).ifPresent(addHeader);
-		getAttribute(document, HEADER_EMAIL).ifPresent(addHeader);
-		getAttribute(document, HEADER_TELEFON).ifPresent(addHeader);
-		getAttribute(document, HEADER_STRASSE).ifPresent(addHeader);
-		getAttribute(document, HEADER_PLZ).ifPresent(addHeader);
-		getAttribute(document, HEADER_ORT).ifPresent(addHeader);
-		return map;
-	}
-
-	Optional<Attr> getAttribute(Document document, String name) {
-		return Optional.ofNullable(document.getDocumentElement().getAttributeNode(name));
-	}
-}
\ No newline at end of file
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapper.java
deleted file mode 100644
index db6bc571cea5ba0c9897dfef2bd7ded128ca9c35..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapper.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.util.List;
-import java.util.UUID;
-
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.common.binaryfile.TempFileUtils;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-
-@Component
-class DepositRequestIncomingFileMapper {
-
-	List<IncomingFile> mapFiles(Deposit depositData) {
-		return depositData.getData().getAttachments().stream()
-				.map(this::buildIncomingFile).toList();
-	}
-
-	private IncomingFile buildIncomingFile(Attachment attachment) {
-		var file = TempFileUtils.writeTmpFile(attachment.content);
-
-		return IncomingFile.builder()
-				.id(UUID.randomUUID().toString())
-				.vendorId(attachment.getId())
-				.name(attachment.getName())
-				.file(file)
-				.contentType(attachment.getContentType())
-				.size(attachment.getContent().length)
-				.build();
-	}
-}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapper.java
deleted file mode 100644
index 6cd2ec7ceadb5a02f19ce3560858d3cb224d26eb..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapper.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import org.springframework.stereotype.Component;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-
-@Component
-class FormDataIncomingFileMapper {
-
-	int countAttachments(Document document) {
-		return document.getElementsByTagName("file").getLength();
-	}
-
-	List<IncomingFileGroup> mapAttachments(Document document) {
-		List<IncomingFileGroup> incomingFileGroups = new ArrayList<>();
-		NodeList files = document.getElementsByTagName("file");
-
-		for (int idx = 0; idx < files.getLength(); idx++) {
-			String parentNodeName = buildParentNodeName(files.item(idx).getParentNode().getNodeName());
-			IncomingFileGroup group = getIncomingFileGroup(incomingFileGroups, parentNodeName);
-			var updatedGroup = group.toBuilder().file(mapNodeToIncomingFile(files.item(idx))).build();
-			incomingFileGroups.remove(group);
-			incomingFileGroups.add(updatedGroup);
-		}
-
-		return incomingFileGroups;
-	}
-
-	String buildParentNodeName(String parentNodeName) {
-		return parentNodeName.replaceAll("-item$", "");
-	}
-
-	private IncomingFile mapNodeToIncomingFile(Node item) {
-		return IncomingFile.builder()
-				.id(UUID.randomUUID().toString())
-				.vendorId(item.getAttributes().getNamedItem("id").getNodeValue())
-				.name(item.getFirstChild().getTextContent())
-				.contentType(item.getAttributes().getNamedItem("content-type").getNodeValue())
-				.size(Integer.valueOf(item.getAttributes().getNamedItem("length").getNodeValue()))
-				.build();
-	}
-
-	private IncomingFileGroup getIncomingFileGroup(List<IncomingFileGroup> incomingFileGroups, String parentNodeName) {
-		return incomingFileGroups.stream()
-				.filter(group -> group.getName().equals(parentNodeName))
-				.findFirst()
-				.orElseGet(() -> {
-					IncomingFileGroup fileGroup = IncomingFileGroup.builder().name(parentNodeName).build();
-					incomingFileGroups.add(fileGroup);
-					return fileGroup;
-				});
-	}
-}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpoint.java
similarity index 92%
rename from intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java
rename to intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpoint.java
index 85fba9a36193a7303b83c4dce077ed65dac682e7..c562cae01b6d903da745260d7e31f29c9b39fb63 100644
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java
+++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpoint.java
@@ -37,11 +37,12 @@ import org.springframework.ws.server.endpoint.annotation.RequestPayload;
 import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
 
 import de.ozgcloud.eingang.semantik.SemantikAdapter;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Endpoint
 @Log4j2
-public class FormDataEndpoint {
+public class IntelliFormEndpoint {
 
 	private static final String NAMESPACE_URI = "http://xmlns.cit.de/intelliform/2009/webservices/backend";
 
@@ -50,8 +51,9 @@ public class FormDataEndpoint {
 	private static final QName _DepositResponse_QNAME = new QName(NAMESPACE_URI, "depositResponse");
 	private static final QName _PrefillResponse_QNAME = new QName(NAMESPACE_URI, "prefillResponse");
 
+
 	@Autowired
-	private SemantikFormDataMapper semantikFormDataMapper;
+	private IntelliFormMapper intelliFormMapper;
 	@Autowired
 	private SemantikAdapter semantikAdapter;
 
@@ -60,7 +62,8 @@ public class FormDataEndpoint {
 	public JAXBElement<DepositResponse> inputFormData(@RequestPayload Deposit deposit)
 			throws IOException, ParserConfigurationException {
 		try {
-			semantikAdapter.processFormData(semantikFormDataMapper.mapToFormData(deposit));
+			var formData = intelliFormMapper.mapToFormData(deposit.getData());
+			semantikAdapter.processFormData(formData);
 		} catch (Exception e) {
 			LOG.error("Error processing form data", e);
 			throw e;
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/IntelliFormMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/IntelliFormMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..b073dd971016dbdf7b7930efc27309a1682eb65c
--- /dev/null
+++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/IntelliFormMapper.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.eingang.intelliform;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import de.ozgcloud.eingang.common.xml.XMLHelper;
+import lombok.RequiredArgsConstructor;
+
+@Component
+@RequiredArgsConstructor
+class IntelliFormMapper {
+
+	public FormData mapToFormData(DepositData depositData) {
+		// Transform deposit data attachments to incoming files
+		Map<String, IncomingFile> incomingFileMap = depositData.getAttachments()
+				.stream()
+				.collect(
+						Collectors.toMap(Attachment::getId, this::mapAttachmentToIncomingFile)
+				);
+
+		// Parse the primary <myForm> xml representation
+		Document document = XMLHelper.parseDocument(
+				// Expect that the <primaryDataAttachmentId> refers to the XML file (and the <primaryFormAttachmentId> to the PDF file)
+				getIncomingFileById(depositData.getPrimaryDataAttachmentId(), incomingFileMap)
+		);
+
+		// Find ids of <file> attachments
+		var attachmentFileIds = findAttachmentIds(document);
+		var attachments = attachmentFileIds.stream()
+				.map(id -> getIncomingFileById(id, incomingFileMap))
+				.map(this::createSingularFileGroup)
+				.toList();
+		var representations = getNamesWithout(incomingFileMap.keySet(), attachmentFileIds).stream()
+				.map(id -> getIncomingFileById(id, incomingFileMap))
+				.toList();
+		return FormData.builder()
+				// Put each <file> attachment in a separate file group
+				.attachments(attachments)
+				.numberOfAttachments(attachments.size())
+				// If a deposit attachment is not referenced by <file> it is interpreted as a representation
+				.representations(representations)
+				.numberOfRepresentations(representations.size())
+				.build();
+	}
+
+	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));
+		}
+		return incomingFileMap.get(id);
+	}
+
+	private IncomingFileGroup createSingularFileGroup(IncomingFile incomingFile) {
+		return IncomingFileGroup.builder().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();
+	}
+
+	private List<String> findAttachmentIds(Document document) {
+		return streamElements(document.getElementsByTagName("file"))
+				.map(element -> element.getAttribute("id"))
+				.toList();
+	}
+
+	private Stream<Element> streamElements(NodeList nodeList) {
+		return IntStream.range(0, nodeList.getLength())
+				.mapToObj(nodeList::item)
+				.map(Element.class::cast);
+	}
+
+	IncomingFile mapAttachmentToIncomingFile(Attachment attachment) {
+		var file = TempFileUtils.writeTmpFile(attachment.content);
+		return IncomingFile.builder()
+				.id(UUID.randomUUID().toString())
+				.vendorId(attachment.id)
+				.name(attachment.name)
+				.contentType(attachment.contentType)
+				.size(file.length())
+				.file(file)
+				.build();
+	}
+}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculator.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculator.java
deleted file mode 100644
index 9018f33263566ab69c239614ca9d6f07aec81afc..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-
-@Component
-public class RepresentationsCalculator {
-
-	List<IncomingFile> calculateRepresentations(List<IncomingFileGroup> formDataFileGroups, List<IncomingFile> depositRequestFiles) {
-
-		return depositRequestFiles.stream()
-				.filter(file -> !formDataContainsFile(formDataFileGroups, file))
-				.collect(Collectors.toList());
-	}
-
-	private boolean formDataContainsFile(List<IncomingFileGroup> formDataFileGroups, IncomingFile depositDataFile) {
-
-		return formDataFileGroups.stream()
-				.anyMatch(fileGroup -> fileGroup.getFiles().stream()
-						.anyMatch(file -> file.getVendorId().equals(depositDataFile.getVendorId())));
-	}
-}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapper.java
deleted file mode 100644
index f4796328f0f9469c17291a9f4dfda6655c1213cf..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapper.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.io.ByteArrayInputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.w3c.dom.Document;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
-import lombok.RequiredArgsConstructor;
-
-//TODO Naming prüfen - er scheint mir nicht semantik zu mappen und befindet sich auch nicht im entsprechenden Modul
-@Component
-@RequiredArgsConstructor
-class SemantikFormDataMapper {
-	static final String FILE = "file";
-
-	static final String CONTENT_FORMDATA_FILENAME_SUFFIX = "-Daten.xml";
-
-	static final String ATTACHMENTS_FIELD = "depositAttachments";
-
-	static final String ATTACHMENT_ID = "id";
-	static final String ATTACHMENT_NAME = "name";
-	static final String ATTACHMENT_DESCRIPTION = "description";
-	static final String ATTACHMENT_ATTRIBUTES = "attributes";
-	static final String ATTACHMENT_CONTENT = "content";
-	static final String ATTACHMENT_CONTENT_TYPE = "contentType";
-
-	static final String HEADER_FIELD = "header";
-
-	static final String HEADER_ID = "t:id";
-	static final String HEADER_TIMESTAMP = "t:timestamp";
-	static final String HEADER_FORM_ID = "t:form-id";
-	static final String HEADER_FORM = "t:form";
-	static final String HEADER_SENDER = "t:sender";
-	static final String HEADER_CUSTOMER = "t:customer";
-	static final String HEADER_CUSTOMER_ID = "t:customer-id";
-	static final String HEADER_CLIENT = "t:client";
-	static final String HEADER_CLIENT_ID = "t:client-id";
-
-	@Autowired
-	private final XmlToJavaMapsMapper xmlToJavaMapsMapper;
-
-	@Autowired
-	private final FormDataIncomingFileMapper formDataIncomingFileMapper;
-
-	@Autowired
-	private final RepresentationsCalculator incomingFilesService;
-
-	@Autowired
-	private final DepositRequestIncomingFileMapper depositRequestFilesMapper;
-
-	@Autowired
-	private final AttachmentsContentAdder attachmentsContentAdder;
-
-	@Autowired
-	private final CustomHeaderReader customHeaderReader;
-
-	public FormData mapToFormData(Deposit depositData) {
-		var xmlFormDataStream = getXmlFormData(depositData.getData());
-
-		var document = xmlToJavaMapsMapper.parseAsW3cDocument(new ByteArrayInputStream(xmlFormDataStream));
-		var formDataMap = xmlToJavaMapsMapper.mapXmlToJavaMaps(document);
-
-		addFiles(document, depositRequestFilesMapper.mapFiles(depositData), formDataMap);
-
-		addHeader(document, formDataMap);
-
-		return FormData.builder().formData(Collections.unmodifiableMap(formDataMap)).build();
-	}
-
-	private byte[] getXmlFormData(DepositData depositData) {
-		var primaryId = depositData.getPrimaryDataAttachmentId();
-
-		return depositData.getAttachments().stream()
-				.filter(attachment -> StringUtils.equals(attachment.getId(), primaryId))
-				.map(Attachment::getContent)
-				.findFirst()
-				.orElseThrow(() -> new RuntimeException("Request does not contain primary data attachment"));
-	}
-
-	private void addFiles(Document document, List<IncomingFile> depositRequestFiles, Map<String, Object> formDataMap) {
-		List<IncomingFileGroup> attachments = formDataIncomingFileMapper.mapAttachments(document);
-		attachments = attachmentsContentAdder.addContentToAttachments(attachments, depositRequestFiles);
-
-		List<IncomingFile> representations = incomingFilesService.calculateRepresentations(attachments, depositRequestFiles);
-
-		formDataMap.put(FilesMapperHelper.FIELD_NAME_MAPPED_FILES, Map.of(
-				FilesMapperHelper.ATTACHMENTS, attachments,
-				FilesMapperHelper.REPRESENTATIONS, representations));
-
-		removeMappedFileReferences(attachments, formDataMap);
-	}
-
-	void removeMappedFileReferences(List<IncomingFileGroup> attachments, Map<String, Object> formDataMap) {
-		attachments.forEach(group -> group.getFiles().stream().map(inFile -> getReferenceName(inFile.getVendorId(), formDataMap)).toList().stream()
-				.forEach(ref -> ref.ifPresent(entry -> formDataMap.remove(entry.getKey()))));
-	}
-
-	@SuppressWarnings("unchecked")
-	Optional<Map.Entry<String, Object>> getReferenceName(String vendorId, Map<String, Object> formDataMap) {
-		return formDataMap.entrySet().stream().filter(entry -> {
-			Object file = null;
-
-			if (entry.getValue() instanceof Map) {
-				file = ((Map<String, Object>) entry.getValue()).get(FILE);
-			}
-
-			return Objects.nonNull(file) && ((Map<String, String>) file).containsValue(vendorId);
-
-		}).findFirst();
-	}
-
-	private void addHeader(Document document, Map<String, Object> formData) {
-		formData.put(HEADER_FIELD, createHeaderMap(document));
-	}
-
-	private Map<String, Object> createHeaderMap(Document document) {
-		var map = new HashMap<String, Object>();
-		map.put(HEADER_ID, document.getDocumentElement().getAttribute(HEADER_ID));
-		map.put(HEADER_TIMESTAMP, document.getDocumentElement().getAttribute(HEADER_TIMESTAMP));
-		map.put(HEADER_FORM_ID, document.getDocumentElement().getAttribute(HEADER_FORM_ID));
-		map.put(HEADER_FORM, document.getDocumentElement().getAttribute(HEADER_FORM));
-		map.put(HEADER_SENDER, document.getDocumentElement().getAttribute(HEADER_SENDER));
-		map.put(HEADER_CUSTOMER, document.getDocumentElement().getAttribute(HEADER_CUSTOMER));
-		map.put(HEADER_CUSTOMER_ID, document.getDocumentElement().getAttribute(HEADER_CUSTOMER_ID));
-		map.put(HEADER_CLIENT, document.getDocumentElement().getAttribute(HEADER_CLIENT));
-		map.put(HEADER_CLIENT_ID, document.getDocumentElement().getAttribute(HEADER_CLIENT_ID));
-		map.putAll(customHeaderReader.getHeader(document));
-		return map;
-	}
-}
\ No newline at end of file
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java
index 36b48dced9adf7c3c8c3189870f241870a44bdbf..940be0ebe3f5f6ad073ead1ac34756c8bd27b4e4 100644
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentTestFactory.java
@@ -38,9 +38,13 @@ public class AttachmentTestFactory {
 				t:form-id="waffen/kleinerWaffenschein"
 				t:customer="Einheitlicher Ansprechpartner" t:customer-id="ea-sh"
 				t:client="Schleswig-Holstein"
-				t:client-id="land"></myForm>""";
+				t:client-id="land">
+				  <Upload1>
+				    <file content-type="image/png" description="" id="VendorId3333" length="155251">Image.png</file>
+			      </Upload1>
+			    </myForm>""";
 	public static final byte[] XML_CONTENT = XML_CONTENT_STRING.getBytes();
-	public static final String XML_ID = "myForm-xml";
+	public static final String XML_ATTACHMENT_ID = "myForm-xml";
 	public static final String XML_NAME = "XML-Daten.xml";
 
 	public static final String PDF_ATTACHMENT_CONTENT_TYPE = "application/pdf";
@@ -48,6 +52,11 @@ public class AttachmentTestFactory {
 	public static final String PDF_ATTACHMENT_NAME = "Scan1.pdf";
 	public static final String PDF_ATTACHMENT_ID = "VendorId2222";
 
+	public static final String PNG_ATTACHMENT_CONTENT_TYPE = "application/pdf";
+	public static final byte[] PNG_ATTACHMENT_CONTENT = "TestContent3".getBytes();
+	public static final String PNG_ATTACHMENT_NAME = "Image.png";
+	public static final String PNG_ATTACHMENT_ID = "VendorId3333";
+
 	public static final String ATTRIBUTES_ENTRY_KEY = "X-IntelliForm-Signed";
 	public static final String ATTRIBUTES_ENTRY_VALUE = "false";
 
@@ -55,7 +64,7 @@ public class AttachmentTestFactory {
 		var attachment = new Attachment();
 		attachment.getAttributes().add(createAttributesEntry());
 		attachment.setContentType(XML_CONTENT_TYPE);
-		attachment.setId(XML_ID);
+		attachment.setId(XML_ATTACHMENT_ID);
 		attachment.setName(XML_NAME);
 		attachment.setContent(XML_CONTENT);
 		return attachment;
@@ -71,10 +80,20 @@ public class AttachmentTestFactory {
 		return attachment;
 	}
 
+	public static Attachment createPng() {
+		var attachment = new Attachment();
+		attachment.getAttributes().add(createAttributesEntry());
+		attachment.setContent(PNG_ATTACHMENT_CONTENT);
+		attachment.setContentType(PNG_ATTACHMENT_CONTENT_TYPE);
+		attachment.setId(PNG_ATTACHMENT_ID);
+		attachment.setName(PNG_ATTACHMENT_NAME);
+		return attachment;
+	}
+
 	private static Entry createAttributesEntry() {
 		var attributesEntry = new Entry();
 		attributesEntry.setKey(ATTRIBUTES_ENTRY_KEY);
 		attributesEntry.setValue(ATTRIBUTES_ENTRY_VALUE);
 		return attributesEntry;
 	}
-}
\ No newline at end of file
+}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdderTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdderTest.java
deleted file mode 100644
index eb1f646706f25d8a2f7861e39092522f4ec8b578..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/AttachmentsContentAdderTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory;
-import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
-import lombok.SneakyThrows;
-
-class AttachmentsContentAdderTest {
-
-	AttachmentsContentAdder service;
-
-	private List<IncomingFileGroup> attachments;
-
-	private List<IncomingFile> depositRequestFiles;
-
-	@BeforeEach
-	void init() {
-
-		service = new AttachmentsContentAdder();
-
-		attachments = List.of(IncomingFileGroupTestFactory.createBuilder().clearFiles()
-				.files(List.of(IncomingFileTestFactory.createBuilder().file(null).build())).build());
-
-		depositRequestFiles = List.of(IncomingFileTestFactory.create());
-	}
-
-	@SneakyThrows
-	@Test
-	void testAddContentToAttachments() {
-		List<IncomingFileGroup> attachmentsWithContent = service.addContentToAttachments(attachments, depositRequestFiles);
-
-		assertThat(attachmentsWithContent.get(0).getFiles().get(0).getContentStream()).hasBinaryContent(IncomingFileTestFactory.CONTENT);
-	}
-}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderReaderTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderReaderTest.java
deleted file mode 100644
index eb435c85ecd0d0dc5214f7a595abc7bd9632f396..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderReaderTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-class CustomHeaderReaderTest {
-
-	@InjectMocks
-	private CustomHeaderReader reader;
-
-	@Mock
-	private Document document;
-	@Mock
-	private Element element;
-	@Mock
-	private Attr attribute;
-
-	@BeforeEach
-	void setup() {
-		when(document.getDocumentElement()).thenReturn(element);
-	}
-
-	@Test
-	void shouldNotAddIfNotPresent() {
-		var formData = reader.getHeader(document);
-
-		assertThat(formData).isEmpty();
-	}
-
-	@Nested
-	class TestHeaderAdded {
-
-		@BeforeEach
-		void setup() {
-			when(element.getAttributeNode(any())).thenReturn(attribute);
-		}
-
-		@Test
-		void shouldAddPostfachId() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_POSTFACH_ID);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.POSTFACH_ID);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_POSTFACH_ID, CustomHeaderTestFactory.POSTFACH_ID);
-		}
-
-		@Test
-		void shouldAddVorname() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_VORNAME);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.VORNAME);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_VORNAME, CustomHeaderTestFactory.VORNAME);
-		}
-
-		@Test
-		void shouldAddNachname() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_NACHNAME);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.NACHNAME);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_NACHNAME, CustomHeaderTestFactory.NACHNAME);
-		}
-
-		@Test
-		void shouldAddGeburtsname() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_GEBURTSNAME);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.GEBURTSNAME);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_GEBURTSNAME, CustomHeaderTestFactory.GEBURTSNAME);
-		}
-
-		@Test
-		void shouldAddGeburtsort() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_GEBURTSORT);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.GEBURTSORT);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_GEBURTSORT, CustomHeaderTestFactory.GEBURTSORT);
-		}
-
-		@Test
-		void shouldAddEmail() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_EMAIL);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.EMAIL);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_EMAIL, CustomHeaderTestFactory.EMAIL);
-		}
-
-		@Test
-		void shouldAddTelefon() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_TELEFON);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.TELEFON);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_TELEFON, CustomHeaderTestFactory.TELEFON);
-		}
-
-		@Test
-		void shouldAddStrasse() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_STRASSE);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.STRASSE);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_STRASSE, CustomHeaderTestFactory.STRASSE);
-		}
-
-		@Test
-		void shouldAddPlz() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_PLZ);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.PLZ);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_PLZ, CustomHeaderTestFactory.PLZ);
-		}
-
-		@Test
-		void shouldAddOrt() {
-			when(attribute.getName()).thenReturn(CustomHeaderReader.HEADER_ORT);
-			when(attribute.getValue()).thenReturn(CustomHeaderTestFactory.ORT);
-
-			var formData = reader.getHeader(document);
-
-			assertThat(formData).containsEntry(CustomHeaderReader.HEADER_ORT, CustomHeaderTestFactory.ORT);
-		}
-	}
-
-}
\ No newline at end of file
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderTestFactory.java
deleted file mode 100644
index acb9fede61f17309e4417fac7149f5d03177c588..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/CustomHeaderTestFactory.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class CustomHeaderTestFactory {
-
-	public static final String POSTFACH_ID = "postfach_id";
-	public static final String VORNAME = "vorname";
-	public static final String NACHNAME = "nachname";
-	public static final String GEBURTSNAME = "geburtsname";
-	public static final String GEBURTSORT = "geburtsort";
-	public static final String EMAIL = "email";
-	public static final String TELEFON = "telefon";
-	public static final String STRASSE = "strasse";
-	public static final String PLZ = "plz";
-	public static final String ORT = "ort";
-
-	public static Map<String, Object> create() {
-		var map = new HashMap<String, Object>();
-		map.put(CustomHeaderReader.HEADER_POSTFACH_ID, POSTFACH_ID);
-		map.put(CustomHeaderReader.HEADER_VORNAME, VORNAME);
-		map.put(CustomHeaderReader.HEADER_NACHNAME, NACHNAME);
-		map.put(CustomHeaderReader.HEADER_GEBURTSNAME, GEBURTSNAME);
-		map.put(CustomHeaderReader.HEADER_GEBURTSORT, GEBURTSORT);
-		map.put(CustomHeaderReader.HEADER_EMAIL, EMAIL);
-		map.put(CustomHeaderReader.HEADER_TELEFON, TELEFON);
-		map.put(CustomHeaderReader.HEADER_STRASSE, STRASSE);
-		map.put(CustomHeaderReader.HEADER_PLZ, PLZ);
-		map.put(CustomHeaderReader.HEADER_ORT, ORT);
-		return map;
-	}
-
-}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/SemantikAdapterConfiguration.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataTestFactory.java
similarity index 62%
rename from intelliform-adapter/src/main/java/de/ozgcloud/eingang/SemantikAdapterConfiguration.java
rename to intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataTestFactory.java
index 7c70b8144a3b5da22da7b1962216c9ada61dceba..7165a5489715577ac427f064bbfdea6103b01a4b 100644
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/SemantikAdapterConfiguration.java
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataTestFactory.java
@@ -21,20 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.eingang;
+package de.ozgcloud.eingang.intelliform;
 
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
+import java.util.Collection;
+import java.util.List;
 
-import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
-import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedAdapter;
+public class DepositDataTestFactory {
 
-@Configuration
-public class SemantikAdapterConfiguration {
+	public static final List<Attachment> ATTACHMENTS = List.of(
+			AttachmentTestFactory.createXmlDaten(),
+			AttachmentTestFactory.createPdf(),
+			AttachmentTestFactory.createPng()
+	);
 
-	@Bean
-	public EngineBasedSemantikAdapter engineBasedSemantikAdapter() {
-		return new AfmEngineBasedAdapter();
+	public static DepositData create(Collection<Attachment> attachments) {
+		var depositData = new DepositData();
+		depositData.setPrimaryDataAttachmentId(AttachmentTestFactory.XML_ATTACHMENT_ID);
+		depositData.getAttachments().addAll(attachments);
+		return depositData;
 	}
-
-}
\ No newline at end of file
+}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapperTest.java
deleted file mode 100644
index 2ae6057c37562eedfee982df019ca6be54bcc7d0..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositRequestIncomingFileMapperTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-
-class DepositRequestIncomingFileMapperTest {
-
-	private DepositRequestIncomingFileMapper mapper;
-
-	@BeforeEach
-	void init() {
-
-		mapper = new DepositRequestIncomingFileMapper();
-	}
-
-	@Test
-	void validateFileCount() {
-
-		List<IncomingFile> files = mapper.mapFiles(DepositTestFactory.create());
-
-		assertThat(files).isNotEmpty().hasSize(2);
-	}
-
-	@Test
-	void validateFile1() {
-
-		List<IncomingFile> files = mapper.mapFiles(DepositTestFactory.create());
-
-		IncomingFile file = files.get(0);
-		assertThat(file.getContentStream()).hasBinaryContent(AttachmentTestFactory.XML_CONTENT);
-		assertThat(file.getContentType()).isEqualTo(AttachmentTestFactory.XML_CONTENT_TYPE);
-		assertThat(file.getVendorId()).isEqualTo(AttachmentTestFactory.XML_ID);
-		assertThat(file.getName()).isEqualTo(AttachmentTestFactory.XML_NAME);
-		assertThat(file.getId()).isNotNull();
-	}
-}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositTestFactory.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositTestFactory.java
deleted file mode 100644
index 174569a3e12d247dd7dc3ac4d9e9ca609298f858..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositTestFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import java.util.List;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
-
-public class DepositTestFactory {
-
-	public static final String ATTACHMENT1_NAME = IncomingFileTestFactory.NAME;
-	public static final String ATTACHMENT1_ID = IncomingFileTestFactory.VENDOR_ID;
-	public static final String ATTACHMENT1_CONTENT_TYPE = IncomingFileTestFactory.CONTENT_TYPE;
-	public static final byte[] ATTACHMENT1_CONTENT = IncomingFileTestFactory.CONTENT;
-
-	public static final String ATTACHMENT2_NAME = "Scan1.pdf";
-	public static final String ATTACHMENT2_ID = "VendorId2222";
-	public static final String ATTACHMENT2_CONTENT_TYPE = "application/pdf";
-	public static final byte[] ATTACHMENT2_CONTENT = "TestContent2".getBytes();
-
-	public static final List<Attachment> ATTACHMENTS = List.of(AttachmentTestFactory.createXmlDaten(), AttachmentTestFactory.createPdf());
-
-	public static Deposit create() {
-		return DepositTestFactory.withAttachments(ATTACHMENTS);
-	}
-
-	static Deposit withData(DepositData data) {
-		Deposit deposit = new Deposit();
-		data.setPrimaryDataAttachmentId(AttachmentTestFactory.XML_ID);
-		deposit.setData(data);
-
-		return deposit;
-	}
-
-	static Deposit withAttachments(List<Attachment> attachments) {
-		Deposit deposit = DepositTestFactory.withData(new DepositData());
-		deposit.getData().getAttachments().addAll(attachments);
-		return deposit;
-	}
-}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapperTest.java
deleted file mode 100644
index 05d11ea152de2367bb23d51555764a15083103d9..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataIncomingFileMapperTest.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.List;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import de.ozgcloud.common.test.TestUtils;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-
-class FormDataIncomingFileMapperTest {
-
-	FormDataIncomingFileMapper mapper = new FormDataIncomingFileMapper();
-
-	private Document document;
-
-	@Test
-	void testBuildParentNodeName() {
-
-		assertThat(mapper.buildParentNodeName("datei_ausweis-item")).isEqualTo("datei_ausweis");
-		assertThat(mapper.buildParentNodeName("datei_ausweis")).isEqualTo("datei_ausweis");
-		assertThat(mapper.buildParentNodeName("datei_-item-ausweis")).isEqualTo("datei_-item-ausweis");
-	}
-
-	@Nested
-	class TestEinfachesFormularMitZweiAnhaengen {
-
-		private static final String GROUP1NAME = "Upload1";
-		private static final String GROUP2NAME = "Upload2";
-
-		List<IncomingFileGroup> attachments;
-
-		@BeforeEach
-		void init() throws ParserConfigurationException, SAXException, IOException {
-
-			String xml = TestUtils.loadTextFile("intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml");
-
-			document = buildDocument(xml);
-
-			attachments = mapper.mapAttachments(document);
-		}
-
-		@Test
-		void validateAttachmentGroupCount() {
-
-			assertThat(attachments).hasSize(2);
-		}
-
-		@Test
-		void validateGroup1Name() {
-
-			assertThat(attachments.get(0).getName()).isEqualTo(GROUP1NAME);
-		}
-
-		@Test
-		void validateGroup1FilesCount() {
-
-			assertThat(attachments.get(0).getFiles()).hasSize(1);
-		}
-
-		@Test
-		void validateGroup1File() {
-
-			IncomingFile file = attachments.get(0).getFiles().get(0);
-
-			assertThat(file.getId()).isNotNull().hasSize(36);
-			assertThat(file.getVendorId()).isEqualTo("assistants.E0FBA361C191F8B723949467AE302BEA24E4745E");
-			assertThat(file.getName()).isEqualTo("Helge1.jpg");
-			assertThat(file.getContentType()).isEqualTo("image/jpeg");
-			assertThat(file.getSize()).isEqualTo(155251);
-		}
-
-		@Test
-		void validateGroup2Name() {
-
-			assertThat(attachments.get(1).getName()).isEqualTo(GROUP2NAME);
-		}
-
-		@Test
-		void validateGroup2FilesCount() {
-
-			assertThat(attachments.get(1).getFiles()).hasSize(1);
-		}
-
-		@Test
-		void validateGroup2File() {
-
-			IncomingFile file = attachments.get(1).getFiles().get(0);
-
-			assertThat(file.getId()).isNotNull().hasSize(36);
-			assertThat(file.getVendorId()).isEqualTo("assistants.52D79E5B2118D1740045AB87151535DCAD24E9A7");
-			assertThat(file.getName()).isEqualTo("Helgetext2.odt");
-			assertThat(file.getContentType()).isEqualTo("application/vnd.oasis.opendocument.text");
-			assertThat(file.getSize()).isEqualTo(7993);
-		}
-	}
-
-	@Nested
-	class TestEinfachesFormularMitZweiAnhaengenVerschachtelt {
-
-		private static final String GROUP1NAME = "datei_ausweis";
-		private static final String GROUP2NAME = "datei_meldebestaetigung";
-
-		List<IncomingFileGroup> attachments;
-
-		@BeforeEach
-		void init() throws ParserConfigurationException, SAXException, IOException {
-
-			String xml = TestUtils.loadTextFile("intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml");
-
-			document = buildDocument(xml);
-
-			attachments = mapper.mapAttachments(document);
-		}
-
-		@Test
-		void validateAttachmentGroupCount() {
-
-			assertThat(attachments).hasSize(2);
-		}
-
-		@Test
-		void validateGroup1Name() {
-
-			assertThat(attachments.get(0).getName()).isEqualTo(GROUP1NAME);
-		}
-
-		@Test
-		void validateGroup1FilesCount() {
-
-			assertThat(attachments.get(0).getFiles()).hasSize(2);
-		}
-
-		@Test
-		void validateGroup1File1() {
-
-			IncomingFile file = attachments.get(0).getFiles().get(0);
-
-			assertThat(file.getId()).isNotNull().hasSize(36);
-			assertThat(file.getVendorId()).isEqualTo("assistants.21B483DAA2DC7900C1D1135E566D0F672CB42832");
-			assertThat(file.getName()).isEqualTo("20210326_133516[1].jpg");
-			assertThat(file.getContentType()).isEqualTo("image/jpeg");
-			assertThat(file.getSize()).isEqualTo(1184319);
-		}
-
-		@Test
-		void validateGroup1File2() {
-
-			IncomingFile file = attachments.get(0).getFiles().get(1);
-
-			assertThat(file.getId()).isNotNull().hasSize(36);
-			assertThat(file.getVendorId()).isEqualTo("assistants.2F1FF737CF4F23191C1952091CB342254EE22A37");
-			assertThat(file.getName()).isEqualTo("20210326_133526[1].jpg");
-			assertThat(file.getContentType()).isEqualTo("image/jpeg");
-			assertThat(file.getSize()).isEqualTo(1384037);
-		}
-
-		@Test
-		void validateGroup2Name() {
-
-			assertThat(attachments.get(1).getName()).isEqualTo(GROUP2NAME);
-		}
-
-		@Test
-		void validateGroup2FilesCount() {
-
-			assertThat(attachments.get(1).getFiles()).hasSize(1);
-		}
-
-		@Test
-		void validateGroup2File() {
-
-			IncomingFile file = attachments.get(1).getFiles().get(0);
-
-			assertThat(file.getId()).isNotNull().hasSize(36);
-			assertThat(file.getVendorId()).isEqualTo("assistants.B20451156C677116B91A4EF2D1E859837B6CE510");
-			assertThat(file.getName()).isEqualTo("20210324_103054[1].jpg");
-			assertThat(file.getContentType()).isEqualTo("image/jpeg");
-			assertThat(file.getSize()).isEqualTo(3066416);
-		}
-	}
-
-	private Document buildDocument(String xml) throws ParserConfigurationException, SAXException, IOException {
-
-		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
-
-		docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-
-		DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
-		Document document = docBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
-
-		// optional, but recommended
-		// http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
-		document.getDocumentElement().normalize();
-
-		return document;
-	}
-
-}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpointITCase.java
similarity index 99%
rename from intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java
rename to intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpointITCase.java
index 2e87bcbd6b297b71c4ece2afa451f258dcae239a..f3144df49776743796da29d54369d4b29e444983 100644
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointITCase.java
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpointITCase.java
@@ -56,7 +56,7 @@ import de.ozgcloud.vorgang.vorgang.GrpcIncomingFileGroup;
 import lombok.SneakyThrows;
 
 @SpringBootTest
-class FormDataEndpointITCase {
+class IntelliFormEndpointITCase {
 
 	private final static String TEST_FILE_PATH = "classpath:itcase/";
 
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpointTest.java
similarity index 88%
rename from intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java
rename to intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpointTest.java
index c6c9381d3ca42453ede63033b277c7e1d00261ef..2466e3842775333cc2926f507463ce42cc898bff 100644
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormEndpointTest.java
@@ -42,23 +42,23 @@ import de.ozgcloud.common.test.TestUtils;
 import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
 import de.ozgcloud.eingang.semantik.SemantikAdapter;
 
-class FormDataEndpointTest {
+class IntelliFormEndpointTest {
 
 	@InjectMocks
-	private FormDataEndpoint formdataEndpoint;
+	private IntelliFormEndpoint formdataEndpointIntelli;
 	@Mock
-	private SemantikFormDataMapper semantikFormDataMapper;
+	private IntelliFormMapper intelliFormMapper;
 	@Mock
 	private SemantikAdapter semantikAdapter;
 
 	@BeforeEach
 	void init() throws SAXException, IOException, ParserConfigurationException {
-		when(semantikFormDataMapper.mapToFormData(any())).thenReturn(FormDataTestFactory.create());
+		when(intelliFormMapper.mapToFormData(any())).thenReturn(FormDataTestFactory.create());
 	}
 
 	@Test
 	void testDepositFormData() throws SAXException, IOException, ParserConfigurationException, URISyntaxException {
-		var response = formdataEndpoint.inputFormData(buildRequest("intelliform/XML-Daten-1.xml"));
+		var response = formdataEndpointIntelli.inputFormData(buildRequest("intelliform/XML-Daten-1.xml"));
 
 		assertThat(response).isNotNull();
 	}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c394c2b2ee230d008e392252f11067af34032d74
--- /dev/null
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/IntelliFormMapperTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.eingang.intelliform;
+
+import static de.ozgcloud.eingang.intelliform.AttachmentTestFactory.*;
+import static de.ozgcloud.eingang.intelliform.DepositDataTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Spy;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import lombok.SneakyThrows;
+
+class IntelliFormMapperTest {
+
+	@Spy
+	private IntelliFormMapper mapper;
+
+	@DisplayName("map to form data")
+	@Nested
+	class TestMapToFormData {
+
+		@Captor
+		private ArgumentCaptor<Attachment> attachmentArgumentCaptor;
+
+		private DepositData depositData;
+
+		@DisplayName("with normal attachments")
+		@Nested
+		class TestWithNormalAttachments {
+			@BeforeEach
+			void mock() {
+				depositData = DepositDataTestFactory.create(ATTACHMENTS);
+			}
+
+			@DisplayName("should throw technical exception if primary xml link is incorrect")
+			@Test
+			void shouldThrowTechnicalExceptionIfPrimaryXmlLinkIsIncorrect() {
+				depositData.setPrimaryDataAttachmentId("incorrect");
+
+				assertThatThrownBy(TestMapToFormData.this::doMapping)
+						.isInstanceOf(TechnicalException.class);
+			}
+
+			@DisplayName("should use map to incoming file method")
+			@Test
+			void shouldUseMapToIncomingFileMethod() {
+				doMapping();
+				verify(mapper, times(ATTACHMENTS.size())).mapAttachmentToIncomingFile(attachmentArgumentCaptor.capture());
+
+				assertThat(attachmentArgumentCaptor.getAllValues()).isEqualTo(ATTACHMENTS);
+			}
+
+			@DisplayName("should return with representations")
+			@Test
+			void shouldReturnWithRepresentations() {
+				var formData = doMapping();
+
+				var incomingFileIds = formData.getRepresentations().stream().map(IncomingFile::getVendorId).toList();
+				assertThat(incomingFileIds).contains(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID);
+			}
+
+			@DisplayName("should return with attachments")
+			@Test
+			void shouldReturnWithAttachments() {
+				var formData = doMapping();
+
+				var incomingFileIds = formData.getAttachments().stream()
+						.flatMap(group -> group.getFiles().stream())
+						.map(IncomingFile::getVendorId)
+						.toList();
+				assertThat(incomingFileIds).contains(PNG_ATTACHMENT_ID);
+			}
+
+			@DisplayName("should return with number of representations")
+			@Test
+			void shouldReturnWithNumberOfRepresentations() {
+				var formData = doMapping();
+
+				assertThat(formData.getNumberOfRepresentations()).isEqualTo(2);
+			}
+		}
+
+		@DisplayName("with empty attachments")
+		@Nested
+		class TestWithEmptyAttachments {
+			@DisplayName("should throw technical exception")
+			@Test
+			void shouldThrowTechnicalException() {
+				depositData = DepositDataTestFactory.create(Collections.emptyList());
+
+				assertThatThrownBy(TestMapToFormData.this::doMapping)
+						.isInstanceOf(TechnicalException.class);
+			}
+		}
+
+		private FormData doMapping() {
+			return mapper.mapToFormData(depositData);
+		}
+
+		private List<String> expectedAttachmentIds(List<Attachment> attachmentList) {
+			return attachmentList.stream().map(attachment -> attachment.id).toList();
+		}
+
+	}
+
+	@DisplayName("map attachment to incoming file")
+	@Nested
+	class TestMapAttachmentToIncomingFile {
+		private Attachment attachment;
+
+		@BeforeEach
+		void mock() {
+			attachment = AttachmentTestFactory.createXmlDaten();
+		}
+
+		@DisplayName("should have ID")
+		@Test
+		void shouldHaveId() {
+			var incomingFile = doMapping();
+
+			assertThat(incomingFile.getId()).isNotNull();
+		}
+
+		@DisplayName("should have vendor ID")
+		@Test
+		void shouldHaveVendorId() {
+			var incomingFile = doMapping();
+
+			assertThat(incomingFile.getVendorId()).isEqualTo(XML_ATTACHMENT_ID);
+		}
+
+		@DisplayName("should have name")
+		@Test
+		void shouldHaveName() {
+			var incomingFile = doMapping();
+
+			assertThat(incomingFile.getName()).isEqualTo(XML_NAME);
+		}
+
+		@DisplayName("should have content type")
+		@Test
+		void shouldHaveContentType() {
+			var incomingFile = doMapping();
+
+			assertThat(incomingFile.getName()).isEqualTo(XML_NAME);
+		}
+
+		@DisplayName("should have size")
+		@Test
+		void shouldHaveSize() {
+			var incomingFile = doMapping();
+
+			assertThat(incomingFile.getSize()).isEqualTo(XML_CONTENT.length);
+		}
+
+		@DisplayName("should have file with content")
+		@SneakyThrows
+		@Test
+		void shouldHaveFileWithContent() {
+			var incomingFile = doMapping();
+
+			var content = FileUtils.readFileToString(incomingFile.getFile(), Charset.defaultCharset());
+			assertThat(content).isEqualTo(XML_CONTENT_STRING);
+		}
+
+		private IncomingFile doMapping() {
+			return mapper.mapAttachmentToIncomingFile(attachment);
+		}
+	}
+
+}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculatorTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculatorTest.java
deleted file mode 100644
index 36ac0cb7e2cff2cd68c210262b7d1360b8a68d9e..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/RepresentationsCalculatorTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory;
-import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
-
-class RepresentationsCalculatorTest {
-
-	private static final String REPRESENTATION_VENDOR_ID_1 = "REPRESENTATION_VENDOR_ID_1";
-	private static final String REPRESENTATION_VENDOR_ID_2 = "REPRESENTATION_VENDOR_ID_2";
-
-	private RepresentationsCalculator service;
-
-	@BeforeEach
-	void init() {
-
-		service = new RepresentationsCalculator();
-	}
-
-	@Nested
-	class CalculateRepresentations {
-
-		private List<IncomingFile> representations;
-
-		@BeforeEach
-		void init() {
-
-			List<IncomingFile> depositDataFiles = List.of(
-					IncomingFileTestFactory.createBuilder().vendorId(REPRESENTATION_VENDOR_ID_1).build(),
-					IncomingFileTestFactory.create(),
-					IncomingFileTestFactory.createBuilder().vendorId(REPRESENTATION_VENDOR_ID_2).build());
-
-			List<IncomingFileGroup> formDataFileGroups = List.of(IncomingFileGroupTestFactory.create());
-
-			representations = service.calculateRepresentations(formDataFileGroups, depositDataFiles);
-		}
-
-		@Test
-		void calculateRepresentations() {
-
-			assertThat(representations).hasSize(2);
-		}
-
-		@Test
-		void validateRepresentation1() {
-
-			assertThat(representations.get(0).getVendorId()).isEqualTo(REPRESENTATION_VENDOR_ID_1);
-		}
-
-		@Test
-		void validateRepresentation2() {
-
-			assertThat(representations.get(1).getVendorId()).isEqualTo(REPRESENTATION_VENDOR_ID_2);
-		}
-	}
-}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapperTest.java
deleted file mode 100644
index 3bf90315f3d0be4e23ea2de093908455ad32b18e..0000000000000000000000000000000000000000
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/SemantikFormDataMapperTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.intelliform;
-
-import static de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.xml.sax.SAXException;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
-
-class SemantikFormDataMapperTest {
-
-	private SemantikFormDataMapper mapper;
-
-	@Mock
-	private CustomHeaderReader customHeaderReader;
-
-	@BeforeEach
-	void setup() {
-		mapper = new SemantikFormDataMapper(new XmlToJavaMapsMapper(), new FormDataIncomingFileMapper(),
-				new RepresentationsCalculator(), new DepositRequestIncomingFileMapper(), new AttachmentsContentAdder(), customHeaderReader);
-	}
-
-	@Nested
-	class TestMapFormData {
-
-		private final Deposit deposit = DepositTestFactory.create();
-
-		@Test
-		void shouldMapIdField() throws SAXException, IOException, ParserConfigurationException {
-			var formData = mapToFormData(deposit);
-
-			assertThat(formData.getId()).isNotNull();
-		}
-
-		@Test
-		void shouldRemoveFileReferences() {
-			Map<String, Object> formDataMap = new HashMap<>(Map.of(FILE_REF1, Map.of(SemantikFormDataMapper.FILE, Map.of(ID, VENDOR_ID_XXX))));
-
-			mapper.removeMappedFileReferences(FILE_GROUPS, formDataMap);
-
-			assertThat(formDataMap).doesNotContainKey(FILE_REF1);
-		}
-
-		@Nested
-		class TestMapDepositRepresentations {
-
-			@Test
-			void shouldMap() throws SAXException, IOException, ParserConfigurationException {
-				var formData = mapToFormData(deposit);
-
-				assertThat(getRepresentations(formData)).hasSize(2);
-			}
-
-			@Test
-			void shouldContainsXmlData() {
-				var formData = mapToFormData(deposit);
-
-				var xmlRepresentation = getRepresentations(formData).stream()
-						.filter(xml -> xml.getContentType().equals(AttachmentTestFactory.XML_CONTENT_TYPE)).findFirst();
-				assertThat(xmlRepresentation).isPresent();
-			}
-
-			@Test
-			void shouldContainsPdfData() {
-				var formData = mapToFormData(deposit);
-
-				var pdfRepresentation = getRepresentations(formData).stream()
-						.filter(pdf -> pdf.getContentType().equals(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT_TYPE)).findFirst();
-				assertThat(pdfRepresentation).isPresent();
-			}
-
-			@Test
-			void shouldContainsPdfAttributes() {
-				var formData = mapToFormData(deposit);
-
-				var pdfAttachment = getRepresentations(formData).stream()
-						.filter(pdf -> pdf.getContentType().equals(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT_TYPE)).findFirst();
-
-				assertThat(pdfAttachment).isPresent();
-				assertThat(pdfAttachment.get().getContentType()).isEqualTo(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT_TYPE);
-				assertThat(pdfAttachment.get().getVendorId()).isEqualTo(AttachmentTestFactory.PDF_ATTACHMENT_ID);
-				assertThat(pdfAttachment.get().getName()).isEqualTo(AttachmentTestFactory.PDF_ATTACHMENT_NAME);
-				assertThat(pdfAttachment.get().getContentStream()).hasBinaryContent(AttachmentTestFactory.PDF_ATTACHMENT_CONTENT);
-			}
-
-			@SuppressWarnings("unchecked")
-			private List<IncomingFile> getRepresentations(FormData formData) {
-				return (List<IncomingFile>) ((Map<String, Object>) formData.getFormData().get(FilesMapperHelper.FIELD_NAME_MAPPED_FILES))
-						.get(FilesMapperHelper.REPRESENTATIONS);
-			}
-		}
-
-		@Nested
-		class TestMapHeader {
-
-			@Test
-			void shouldMapHeader() {
-				var formData = mapToFormData(deposit);
-
-				var formHeader = getHeader(formData);
-				assertThat(formHeader)
-						.containsEntry(SemantikFormDataMapper.HEADER_ID, "20201118365670866101")
-						.containsEntry(SemantikFormDataMapper.HEADER_TIMESTAMP, "2020-11-18T09:09:27.627Z")
-						.containsEntry(SemantikFormDataMapper.HEADER_FORM_ID, "waffen/kleinerWaffenschein")
-						.containsEntry(SemantikFormDataMapper.HEADER_FORM, "Kleiner Waffenschein gem. § 10 Abs. 4 Satz 4 Waffengesetz (WaffG)")
-						.containsEntry(SemantikFormDataMapper.HEADER_SENDER, "afm.schleswig-holstein.de")
-						.containsEntry(SemantikFormDataMapper.HEADER_CUSTOMER, "Einheitlicher Ansprechpartner")
-						.containsEntry(SemantikFormDataMapper.HEADER_CUSTOMER_ID, "ea-sh")
-						.containsEntry(SemantikFormDataMapper.HEADER_CLIENT, "Schleswig-Holstein")
-						.containsEntry(SemantikFormDataMapper.HEADER_CLIENT_ID, "land");
-			}
-
-			@Test
-			void shouldAddBayernHeader() {
-				Map<String, Object> bayernHeader = Map.of(CustomHeaderReader.HEADER_POSTFACH_ID, CustomHeaderTestFactory.POSTFACH_ID);
-				when(customHeaderReader.getHeader(any())).thenReturn(bayernHeader);
-
-				var formData = mapToFormData(deposit);
-
-				verify(customHeaderReader).getHeader(any());
-				assertThat(getHeader(formData)).containsEntry(CustomHeaderReader.HEADER_POSTFACH_ID, CustomHeaderTestFactory.POSTFACH_ID);
-			}
-
-			@SuppressWarnings("unchecked")
-			private Map<String, Object> getHeader(FormData formData) {
-				return (Map<String, Object>) formData.getFormData().get(SemantikFormDataMapper.HEADER_FIELD);
-			}
-		}
-
-		private FormData mapToFormData(Deposit deposit) {
-			return mapper.mapToFormData(deposit);
-		}
-	}
-}
\ No newline at end of file
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java
index 74840e2f51139b08cf49bb19bb7016a71dfa2bd9..ccf6f3ce4aad5162e9364c079bf07856bdc74a1d 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/SemantikAdapter.java
@@ -23,7 +23,8 @@
  */
 package de.ozgcloud.eingang.semantik;
 
-import java.util.Objects;
+import java.util.List;
+import java.util.Optional;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -32,15 +33,15 @@ import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.router.VorgangService;
 import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
 import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter;
+import lombok.RequiredArgsConstructor;
 
 @Service
 public class SemantikAdapter {
 
-	@Autowired(required = false)
-	private EngineBasedSemantikAdapter engineBasedAdapter;
+	@Autowired
+	private List<EngineBasedSemantikAdapter> engineBasedAdapters;
 	@Autowired
 	private FormBasedSemantikAdapter formBasedAdapter;
-
 	@Autowired
 	private VorgangService vorgangService;
 
@@ -52,13 +53,18 @@ public class SemantikAdapter {
 	}
 
 	private FormData parseByEngineAdapter(FormData formData) {
-		if (Objects.nonNull(engineBasedAdapter)) {
-			return engineBasedAdapter.parseFormData(formData);
-		}
-		return formData;
+		return findResponsibleEngineAdapter(formData)
+				.map(adapter -> adapter.parseFormData(formData))
+				.orElse(formData);
+	}
+
+	Optional<EngineBasedSemantikAdapter> findResponsibleEngineAdapter(FormData formData) {
+		return engineBasedAdapters.stream()
+				.filter(adapter -> adapter.isResponsible(formData))
+				.findFirst();
 	}
 
 	private FormData parseByFormAdapter(FormData formData) {
 		return formBasedAdapter.parseFormData(formData);
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java
index 866b8fc52a49b92460625922df950f46224a6043..a60d4a859c5074a52b634121dedc678ad9bf6e6e 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/EngineBasedSemantikAdapter.java
@@ -28,4 +28,9 @@ import de.ozgcloud.eingang.common.formdata.FormData;
 public interface EngineBasedSemantikAdapter {
 
 	FormData parseFormData(FormData formData);
+
+	@SuppressWarnings("unused")
+	default boolean isResponsible(FormData formData) {
+		return true;
+	}
 }
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java
index 4e5251da5812a678dd2234ab964de002cabd78e8..8ca005996ebcd86ce4b59b03f9cc087ac3c3569a 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerMapper.java
@@ -81,11 +81,11 @@ class AfmAntragstellerMapper implements AfmEngineBasedMapper {
 		return (String) formDataMap.get(POSTFACH_ID);
 	}
 
-	@SuppressWarnings("unchecked")
-	private Optional<Map<String, Object>> getAntragstellerMap(Map<String, Object> formDataMap) {
+	private Optional<LinkedHashMap<String, Object>> getAntragstellerMap(Map<String, Object> formDataMap) {
 		return Optional.ofNullable(formDataMap.get(ANTRAGSTELLER))
 				.or(() -> Optional.ofNullable(formDataMap.get(ANTRAGSTELLER_UPPERCASE)))
-				.map(Map.class::cast).map(LinkedHashMap::new);
+				.map(Map.class::cast)
+				.map(LinkedHashMap<String, Object>::new);
 	}
 
 	private Antragsteller.AntragstellerBuilder addAntragstellerData(Antragsteller.AntragstellerBuilder builder,
@@ -125,4 +125,4 @@ class AfmAntragstellerMapper implements AfmEngineBasedMapper {
 		}
 		return Collections.unmodifiableMap(editableMap);
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java
index 739ef9e7c9fe38bdede62e9812ec9a98821f7297..8f6733cd1d89b68580e8ab128fae413714b87e61 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapter.java
@@ -26,30 +26,52 @@ package de.ozgcloud.eingang.semantik.enginebased.afm;
 import java.util.List;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataUtils;
 import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
+import de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.IntelliFormRepresentationAdapter;
+import lombok.RequiredArgsConstructor;
 
+@Component
 public class AfmEngineBasedAdapter implements EngineBasedSemantikAdapter {
 
+	@Autowired
+	private IntelliFormRepresentationAdapter intelliFormRepresentationAdapter;
+
 	@Autowired
 	private List<AfmEngineBasedMapper> mappers;
 
 	@Override
 	public FormData parseFormData(FormData formData) {
-		var processedFormData = formData;
+		var vorgangNummer = formData.getHeader().getVorgangNummer();
+		var processedFormData = intelliFormRepresentationAdapter.adaptByRepresentations(formData);
 
 		for (var mapper : mappers) {
 			processedFormData = mapper.parseFormData(processedFormData);
 		}
 
-		return removeProcessedData(processedFormData);
+		return removeProcessedData(addVorgangNummer(processedFormData, vorgangNummer));
+	}
+
+	private FormData addVorgangNummer(FormData formData, String vorgangNummer) {
+		return formData.toBuilder()
+				.header(formData.getHeader().toBuilder()
+						.vorgangNummer(vorgangNummer)
+						.build()
+				)
+				.build();
 	}
 
-	FormData removeProcessedData(FormData formData) {
+	private FormData removeProcessedData(FormData formData) {
 		return FormDataUtils.from(formData)
 				.remove(AfmAntragstellerMapper.POSTFACH_ID)
 				.build();
 	}
-}
\ No newline at end of file
+
+	@Override
+	public boolean isResponsible(FormData formData) {
+		return intelliFormRepresentationAdapter.isResponsible(formData);
+	}
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapper.java
similarity index 68%
rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapper.java
rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapper.java
index 6daeceab9dfd7e9f397b46fa087792ae4dff7560..e706d63e31d8161b639826fe9f22b06beeda65d1 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapper.java
@@ -29,19 +29,14 @@ import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
 
 @Component
-class AfmAttachedFilesMapper implements AfmEngineBasedMapper {
+class AfmFileCountMapper implements AfmEngineBasedMapper {
 
 	@Override
 	public FormData parseFormData(FormData formData) {
-		var formDataBuilder = formData.toBuilder();
-		FilesMapperHelper.getAttachedFileGroups(formData)
-				.ifPresent(fileGroups -> formDataBuilder
-						.attachments(fileGroups)
-						.numberOfAttachments(FilesMapperHelper.countAttachedFiles(fileGroups)));
-		FilesMapperHelper.getRepresentations(formData)
-				.ifPresent(representations -> formDataBuilder.representations(representations).numberOfRepresentations(representations.size()));
-
-		return FilesMapperHelper.removeProcessedData(formDataBuilder.build());
+		return formData.toBuilder()
+				.numberOfRepresentations(formData.getRepresentations().size())
+				.numberOfAttachments(FilesMapperHelper.countAttachedFiles(formData.getAttachments()))
+				.build();
 	}
 
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..36fb9fa6507228103bb71f8c0d2612d39b868c11
--- /dev/null
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java
@@ -0,0 +1,143 @@
+package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.collections.MapUtils;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Document;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@RequiredArgsConstructor
+@Log4j2
+public class IntelliFormRepresentationAdapter {
+
+	static final String INTELLIFORM_TYPENAME = "http://xmlns.cit.de/intelliform/transaction";
+
+	static final String FILE = "file";
+
+	static final String HEADER_FIELD = "header";
+
+	public static final List<String> HEADER_ATTRIBUTE_NAMES = List.of(
+			"t:id",
+			"t:timestamp",
+			"t:form-id",
+			"t:form",
+			"t:sender",
+			"t:customer",
+			"t:customer-id",
+			"t:client",
+			"t:client-id"
+	);
+	public static final List<String> CUSTOM_HEADER_ATTRIBUTE_NAMES = List.of(
+			"u:saml_legacypostkorbhandle",
+			"u:saml_givenname",
+			"u:saml_surname",
+			"u:saml_placeofbirth",
+			"u:saml_birthname",
+			"u:saml_mail",
+			"u:saml_telephonenumber",
+			"u:saml_postaladdress",
+			"u:saml_postalcode",
+			"u:saml_localityname"
+	);
+
+	private static final Collector<Map.Entry<String, ?>, ?, Map<String, Object>> ORDERED_MAP_ENTRY_COLLECTOR = Collectors.toMap(
+			Map.Entry::getKey,
+			Map.Entry::getValue,
+			(u, v) -> v,
+			LinkedHashMap::new
+	);
+
+	private final XmlToJavaMapsMapper xmlToJavaMapsMapper;
+
+	public boolean isResponsible(FormData formData) {
+		return findIntelliFormXMLRepresentation(formData)
+				.isPresent();
+	}
+
+	Optional<Document> findIntelliFormXMLRepresentation(FormData formData) {
+		return streamXMLDocumentsFromRepresentations(formData)
+				.filter(document -> {
+					var element = document.getDocumentElement();
+					var attribute = element.getAttribute("xmlns:t");
+					return attribute.equals(INTELLIFORM_TYPENAME);
+				})
+				.findFirst();
+	}
+
+	Stream<Document> streamXMLDocumentsFromRepresentations(FormData formData) {
+		return formData.getRepresentations().stream()
+				.filter(representation -> representation.getContentType().contains("xml"))
+				.flatMap(xmlRepresentation -> {
+					try {
+						return Stream.of(xmlToJavaMapsMapper.parseAsW3cDocument(xmlRepresentation.getContentStream()));
+					} catch (TechnicalException exception) {
+						return Stream.empty();
+					}
+				});
+	}
+
+	public FormData adaptByRepresentations(FormData formData) {
+		var document = findIntelliFormXMLRepresentation(formData)
+				.orElseThrow(() -> new TechnicalException("Expect to find IntelliForm XML representation!"));
+
+		return FormData.builder()
+				.representations(formData.getRepresentations())
+				.attachments(formData.getAttachments())
+				.formData(Stream.concat(
+						getFormDataEntriesFromDocument(document, formData.getAttachments()),
+						Map.of(
+								HEADER_FIELD, createHeaderMap(document)
+						).entrySet().stream()
+				).collect(ORDERED_MAP_ENTRY_COLLECTOR))
+				.build();
+	}
+
+	Stream<Map.Entry<String, Object>> getFormDataEntriesFromDocument(Document document, List<IncomingFileGroup> attachments) {
+		Set<String> attachmentVendorIds = attachments.stream()
+				.flatMap(group -> group.getFiles().stream())
+				.map(IncomingFile::getVendorId)
+				.collect(Collectors.toSet());
+
+		return xmlToJavaMapsMapper.mapXmlToJavaMaps(document).entrySet()
+				.stream()
+				.filter(entry -> !isUploadElementWhichRefersToAttachment(entry.getValue(), attachmentVendorIds));
+	}
+
+	private boolean isUploadElementWhichRefersToAttachment(Object element, Set<String> attachmentVendorIds) {
+		return findVendorIdInUploadElementCandidate(element)
+				.map(attachmentVendorIds::contains)
+				.orElse(false);
+	}
+
+	@SuppressWarnings("rawtypes")
+	private Optional<String> findVendorIdInUploadElementCandidate(Object element) {
+		if (element instanceof Map uploadElement) {
+			return Optional.ofNullable(MapUtils.getMap(uploadElement, FILE))
+					.flatMap(fileElement -> Optional.ofNullable(MapUtils.getString(fileElement, "id")));
+		} else {
+			return Optional.empty();
+		}
+	}
+
+	Map<String, Object> createHeaderMap(Document document) {
+		var element = document.getDocumentElement();
+		return Stream.concat(HEADER_ATTRIBUTE_NAMES.stream(), CUSTOM_HEADER_ATTRIBUTE_NAMES.stream().filter(element::hasAttribute))
+				.collect(Collectors.toMap(name -> name, element::getAttribute));
+	}
+
+}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/JsonService.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonService.java
similarity index 93%
rename from intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/JsonService.java
rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonService.java
index fa8c516f641b18f518ec3d19323a01d81a7287c4..04d21f1a271da454917f3a580727e31bc3baac98 100644
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/JsonService.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonService.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.intelliform;
+package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform;
 
 import java.util.List;
 import java.util.Map;
@@ -32,4 +32,4 @@ class JsonService {
 			throw new TechnicalException("Error parsing JSON", e);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapper.java
similarity index 98%
rename from intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapper.java
rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapper.java
index bd7164616db3a639cfe66538da9beafd303aaabf..75409a60e28a1966f85e4b1caa4ecdda90fa569e 100644
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapper.java
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.eingang.intelliform;
+package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -184,4 +184,4 @@ class XmlToJavaMapsMapper {
 			return Collections.emptyList();
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapter.java
similarity index 82%
rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapper.java
rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapter.java
index 6c2292d48b4b596feef5e0abdc3d087099a94d9d..1bb43a80e2f70556be226637d2d63ad78de41efe 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapter.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.semantik.formbased;
+package de.ozgcloud.eingang.semantik.enginebased.dfoerdermittel;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -20,13 +20,15 @@ import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.IncomingFile;
 import de.ozgcloud.eingang.common.formdata.ServiceKonto;
 import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
+import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
 import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
 import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Log4j2
 @Component
-public class DFoerdermittelFormBasedMapper implements FormBasedMapper {
+public class DFoerdermittelEngineBasedSemantikAdapter implements EngineBasedSemantikAdapter {
 
 	private static final String FACHNACHRICHT_SUFFIX = "Fachnachricht.xml";
 	private static final Predicate<IncomingFile> IS_FACHNACHRICHT = inFile -> StringUtils.endsWith(inFile.getName(), FACHNACHRICHT_SUFFIX);
@@ -51,7 +53,9 @@ public class DFoerdermittelFormBasedMapper implements FormBasedMapper {
 		Map<String, Object> fachnachricht = (Map<String, Object>) MapUtils.getMap(formData.getFormData(), KEY_FACHNACHRICHT,
 				Collections.<String, Object>emptyMap());
 
-		var extendedFormData = addServiceKonto(formData, fachnachricht);
+		var extendedFormData = addFormName(formData);
+		extendedFormData = addFormEngineName(extendedFormData);
+		extendedFormData = addServiceKonto(extendedFormData, fachnachricht);
 		return addOrganisationsEinheitId(extendedFormData, fachnachricht);
 	}
 
@@ -82,6 +86,25 @@ public class DFoerdermittelFormBasedMapper implements FormBasedMapper {
 		return zustaendigeStelleBuilder.organisationseinheitenId(orgaId).build();
 	}
 
+	FormData addFormName(FormData formData) {
+		return formData.toBuilder()
+				.header(formData.getHeader().toBuilder()
+						// TODO replace formName with actual name <Title> from Fachnachricht (KOP-2239)
+						.formName("dFördermittelantrag")
+						.build()
+				)
+				.build();
+	}
+
+	FormData addFormEngineName(FormData formData) {
+		return formData.toBuilder()
+				.header(formData.getHeader().toBuilder()
+						.formEngineName("dFördermittelantrag")
+						.build()
+				)
+				.build();
+	}
+
 	String extractPrefix(@NonNull String postfachId) {
 		return postfachId.substring(postfachId.lastIndexOf("/") + 1);
 	}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java
index f4e91092747456556d75874ee1a8cddc12c5dfc2..d63b1e4f5a502a5efce7f280b107422e0ee83a64 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsFilesMapper.java
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.IncomingFile;
 import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-import de.ozgcloud.eingang.semantik.common.ZipAttachmentReader;
+import de.ozgcloud.eingang.common.zip.ZipAttachmentReader;
 import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedAdapter.java
deleted file mode 100644
index a74ff267bd5984e068abd0fc00a9bd6c2469e05d..0000000000000000000000000000000000000000
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedAdapter.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.ozgcloud.eingang.semantik.enginebased.xta;
-
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
-
-public class XtaEngineBasedAdapter implements EngineBasedSemantikAdapter {
-
-	@Autowired
-	private List<XtaEngineBasedMapper> mappers;
-
-	@Override
-	public FormData parseFormData(FormData formData) {
-		var processed = formData;
-
-		for (var mapper : mappers) {
-			processed = mapper.parseFormData(processed);
-		}
-
-		return processed;
-	}
-
-}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedMapper.java
deleted file mode 100644
index 085f7f230d0b65cd06215654e1554c31cce7baeb..0000000000000000000000000000000000000000
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaEngineBasedMapper.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package de.ozgcloud.eingang.semantik.enginebased.xta;
-
-import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper;
-
-public interface XtaEngineBasedMapper extends EngineBasedMapper {
-
-}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapper.java
deleted file mode 100644
index 9a0814f1efa9b86843d27db360a53986091b2dd2..0000000000000000000000000000000000000000
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapper.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package de.ozgcloud.eingang.semantik.enginebased.xta;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Predicate;
-
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.semantik.common.ZipAttachmentReader;
-import lombok.extern.log4j.Log4j2;
-
-@Component
-@Log4j2
-public class XtaZipRepresentationsMapper implements XtaEngineBasedMapper {
-
-	public static final String ZIP_CONTENT_TYPE = "application/zip";
-
-	static final Predicate<IncomingFile> IS_ZIP_FILE = contentType -> ZIP_CONTENT_TYPE.equals(contentType.getContentType());
-
-	@Override
-	public FormData parseFormData(FormData srcFormData) {
-
-		List<IncomingFile> extractedFiles = srcFormData.getRepresentations().stream()
-				.filter(IS_ZIP_FILE)
-				.map(this::extractZip)
-				.flatMap(List::stream)
-				.toList();
-
-		return srcFormData
-				.toBuilder()
-				.representations(extractedFiles)
-				.numberOfRepresentations(srcFormData.getNumberOfRepresentations() + extractedFiles.size()).build();
-	}
-
-	List<IncomingFile> extractZip(IncomingFile zipFile) {
-		try {
-			return ZipAttachmentReader.from(zipFile.getContentStream(), zipFile.getName()).readContent();
-		} catch (RuntimeException e) {
-			LOG.error("Cannot read source ZIP. Not extracting file", e);
-			return Collections.emptyList();
-		}
-	}
-}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/AnliegenId.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/AnliegenId.java
deleted file mode 100644
index 7ae3363c94933a5ea0f5b1a73ddcdacf5ddc22b7..0000000000000000000000000000000000000000
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/AnliegenId.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.eingang.semantik.formbased;
-
-import de.ozgcloud.common.datatype.StringBasedValue;
-
-class AnliegenId extends StringBasedValue {
-
-	private static final long serialVersionUID = 1L;
-
-	AnliegenId(String anliegenId) {
-		super(anliegenId);
-	}
-
-	public static AnliegenId from(String anliegenId) {
-		return new AnliegenId(anliegenId);
-	}
-}
\ No newline at end of file
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java
index 98b3e7fc66f6f4a1ccd849a07c68cc0e6eed9755..dbe206cafc115bf08a30839bab78afbc1933fdb3 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/SemantikAdapterTest.java
@@ -23,25 +23,36 @@
  */
 package de.ozgcloud.eingang.semantik;
 
+import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.List;
+import java.util.Optional;
+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.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.router.VorgangService;
-import de.ozgcloud.eingang.semantik.SemantikAdapter;
 import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
 import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter;
 
 class SemantikAdapterTest {
 
+	@Spy
 	@InjectMocks
 	private SemantikAdapter adapter;
+
+	@Mock
+	private List<EngineBasedSemantikAdapter> engineAdapters;
+
 	@Mock
 	private EngineBasedSemantikAdapter engineAdapter;
 	@Mock
@@ -49,6 +60,39 @@ class SemantikAdapterTest {
 	@Mock
 	private VorgangService vorgangService;
 
+	@DisplayName("find responsible engine adapter")
+	@Nested
+	class TestFindResponsibleEngineAdapter {
+
+		@BeforeEach
+		void mock() {
+			when(engineAdapters.stream()).thenReturn(Stream.of(engineAdapter));
+		}
+
+		@Mock
+		private FormData formData;
+
+		@DisplayName("should return responsible")
+		@Test
+		void shouldReturnResponsible() {
+			when(engineAdapter.isResponsible(any())).thenReturn(true);
+
+			var foundAdapter = adapter.findResponsibleEngineAdapter(formData);
+
+			assertThat(foundAdapter).isEqualTo(Optional.of(engineAdapter));
+		}
+
+		@DisplayName("should return empty if not responsible")
+		@Test
+		void shouldReturnEmptyIfNotResponsible() {
+			when(engineAdapter.isResponsible(any())).thenReturn(false);
+
+			var foundAdapter = adapter.findResponsibleEngineAdapter(formData);
+
+			assertThat(foundAdapter).isNotPresent();
+		}
+	}
+
 	@Nested
 	class TestProcessFormData {
 
@@ -61,10 +105,18 @@ class SemantikAdapterTest {
 
 		@BeforeEach
 		void mockEngineAdapter() {
+			doReturn(Optional.of(engineAdapter)).when(adapter).findResponsibleEngineAdapter(formData);
 			when(engineAdapter.parseFormData(any())).thenReturn(engineAdapterResponse);
 			when(formAdapter.parseFormData(any())).thenReturn(formAdapterResponse);
 		}
 
+		@Test
+		void shouldCallFindEngineAdapter() {
+			adapter.processFormData(formData);
+
+			verify(adapter).findResponsibleEngineAdapter(formData);
+		}
+
 		@Test
 		void shouldCallEngineAdapter() {
 			adapter.processFormData(formData);
@@ -86,4 +138,4 @@ class SemantikAdapterTest {
 			verify(vorgangService).createVorgang(formAdapterResponse);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java
index ff4575a298712beaa7bdc0e8cbe035e83b9c714e..609284d26fccdb41ed91818c5df7ed0161990cdc 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmEngineBasedAdapterTest.java
@@ -24,11 +24,9 @@
 package de.ozgcloud.eingang.semantik.enginebased.afm;
 
 import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -41,50 +39,58 @@ import org.mockito.Spy;
 import org.springframework.test.util.ReflectionTestUtils;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper;
-import de.ozgcloud.eingang.semantik.enginebased.afm.AfmAntragstellerMapper;
-import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedAdapter;
-import de.ozgcloud.eingang.semantik.enginebased.afm.AfmEngineBasedMapper;
+import de.ozgcloud.eingang.common.formdata.FormHeader;
+import de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.IntelliFormRepresentationAdapter;
 
 class AfmEngineBasedAdapterTest {
 
 	@Spy
 	@InjectMocks
 	private AfmEngineBasedAdapter adapter;
-	@Spy
-	private List<EngineBasedMapper> mappers;
 	@Mock
 	private AfmEngineBasedMapper mapper;
 
+	@Mock
+	private IntelliFormRepresentationAdapter intelliFormRepresentationAdapters;
+
 	@DisplayName("Parse form data")
 	@Nested
 	class TestParseFromData {
+		private final String VORGANG_NUMMER = "AAAA-1234";
 
 		private final Map<String, Object> formDataMap = Map.of(AfmAntragstellerMapper.POSTFACH_ID, "postfachIdValue");
-		private final FormData formData = FormData.builder().formData(formDataMap).build();
+		private final FormData formData = FormData.builder()
+				.header(FormHeader.builder()
+						.vorgangNummer(VORGANG_NUMMER)
+						.build()
+				)
+				.formData(formDataMap)
+				.build();
+
+		private final FormData processedFormData = FormData.builder()
+				.formData(formDataMap)
+				.build();
 
 		@BeforeEach
-		void mockMappers() {
+		void mock() {
 			ReflectionTestUtils.setField(adapter, "mappers", Collections.singletonList(mapper));
-		}
 
-		@BeforeEach
-		void mockEngineBasedMapper() {
-			when(mapper.parseFormData(any())).thenReturn(formData);
+			when(mapper.parseFormData(processedFormData)).thenReturn(processedFormData);
+			when(intelliFormRepresentationAdapters.adaptByRepresentations(formData)).thenReturn(processedFormData);
 		}
 
 		@Test
-		void shouldCallMappers() {
+		void shouldCallRepresentationAdapter() {
 			adapter.parseFormData(formData);
 
-			verify(mapper).parseFormData(formData);
+			verify(intelliFormRepresentationAdapters).adaptByRepresentations(formData);
 		}
 
 		@Test
-		void shouldRemoveProcessedData() {
+		void shouldCallMappers() {
 			adapter.parseFormData(formData);
 
-			verify(adapter).removeProcessedData(formData);
+			verify(mapper).parseFormData(processedFormData);
 		}
 
 		@Test
@@ -93,5 +99,14 @@ class AfmEngineBasedAdapterTest {
 
 			assertThat(mappedFormData.getFormData()).doesNotContainKey(AfmAntragstellerMapper.POSTFACH_ID);
 		}
+
+		@DisplayName("should keep vorgang nummer")
+		@Test
+		void shouldKeepVorgangNummer() {
+			var mappedFormData = adapter.parseFormData(formData);
+
+			assertThat(mappedFormData.getHeader().getVorgangNummer()).isEqualTo(VORGANG_NUMMER);
+		}
 	}
+
 }
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapperTest.java
similarity index 75%
rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapperTest.java
rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapperTest.java
index 2643740ae163291151e0573b6b9537514ce0b831..7c63ef8ed048579653880f4ef7904f0b97d9554a 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAttachedFilesMapperTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmFileCountMapperTest.java
@@ -26,44 +26,40 @@ package de.ozgcloud.eingang.semantik.enginebased.afm;
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.List;
-import java.util.Map;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
 import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
 import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory;
 import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
-import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
-import de.ozgcloud.eingang.semantik.enginebased.afm.AfmAttachedFilesMapper;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-class AfmAttachedFilesMapperTest {
+class AfmFileCountMapperTest {
 
 	@Spy
 	@InjectMocks
-	private AfmAttachedFilesMapper mapper;
+	private AfmFileCountMapper mapper;
 
-	private IncomingFileGroup attachmentWithMultipleFiles = IncomingFileGroupTestFactory.createBuilder()
+	private final IncomingFileGroup attachmentWithMultipleFiles = IncomingFileGroupTestFactory.createBuilder()
 			.name("anotherAttachment")
 			.clearFiles()
 			.files(List.of(IncomingFileTestFactory.create(), IncomingFileTestFactory.create()))
 			.build();
 
-	private FormData formData = FormDataTestFactory.createBuilder()
+	private final FormData formData = FormDataTestFactory.createBuilder()
 			.clearAttachments()
-			.formData(Map.of(FilesMapperHelper.FIELD_NAME_MAPPED_FILES,
-					Map.of(FilesMapperHelper.ATTACHMENTS, List.of(IncomingFileGroupTestFactory.create(), attachmentWithMultipleFiles))))
+			.attachments(List.of(IncomingFileGroupTestFactory.create(), attachmentWithMultipleFiles))
 			.build();
 
 	@Nested
 	class TestParseFormData {
 
 		@Test
-		void shouldMapAttachments() {
+		void shouldKeepAttachments() {
 			var parsedFormData = parseFormData();
 
 			assertThat(parsedFormData.getAttachments()).hasSize(2);
@@ -79,7 +75,7 @@ class AfmAttachedFilesMapperTest {
 		}
 
 		@Test
-		void shouldMapRepresentations() {
+		void shouldKeepRepresentations() {
 			var parsedFormData = parseFormData();
 
 			assertThat(parsedFormData.getRepresentations()).hasSize(1);
@@ -92,15 +88,8 @@ class AfmAttachedFilesMapperTest {
 			assertThat(parsedFormData.getNumberOfRepresentations()).isEqualTo(1);
 		}
 
-		@Test
-		void shouldRemoveFilesFromMap() {
-			var parsedFormData = parseFormData();
-
-			assertThat(parsedFormData.getFormData().get(FilesMapperHelper.FIELD_NAME_MAPPED_FILES)).isNull();
-		}
-
 		private FormData parseFormData() {
 			return mapper.parseFormData(formData);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..27be6b86a22cc6658bb7421265e3b914fb990817
--- /dev/null
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapterTest.java
@@ -0,0 +1,456 @@
+package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform;
+
+import static de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.IntelliFormRepresentationAdapter.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+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.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroupTestFactory;
+import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
+
+class IntelliFormRepresentationAdapterTest {
+
+	private static final String DOCUMENT_TEST_KEY = "doc-test-key";
+	private static final String DOCUMENT_TEST_VALUE = "doc-test-value";
+
+	@Spy
+	@InjectMocks
+	IntelliFormRepresentationAdapter adapter;
+
+	@Mock
+	private XmlToJavaMapsMapper xmlToJavaMapsMapper;
+
+	@DisplayName("find IntelliForm XML representation")
+	@Nested
+	class TestFindIntelliFormXmlRepresentation {
+
+		@Mock
+		private FormData formData;
+
+		@DisplayName("should find first with IntelliForm schema")
+		@Test
+		void shouldFindFirstWithIntelliFormSchema() {
+			var schemas = Stream.of(
+					"<root xmlns=\"%s\" />".formatted(INTELLIFORM_TYPENAME),
+					"<root xmlns:t=\"unknown\">first</root>",
+					"<root>second</root>",
+					"<root xmlns:t=\"%s\">third</root>".formatted(INTELLIFORM_TYPENAME),
+					"<root xmlns:t=\"%s\">fourth</root>".formatted(INTELLIFORM_TYPENAME)
+			).map(IntelliFormRepresentationAdapterTest.this::buildXMLDocument);
+			doReturn(schemas).when(adapter).streamXMLDocumentsFromRepresentations(formData);
+
+			var firstWithSchema = adapter.findIntelliFormXMLRepresentation(formData);
+
+			assertThat(firstWithSchema).isPresent();
+			var rootElement = firstWithSchema.get().getDocumentElement();
+			assertThat(rootElement.getTextContent()).isEqualTo("third");
+		}
+	}
+
+	@DisplayName("stream XML documents from representations")
+	@Nested
+	class TestStreamXmlDocumentsFromRepresentations {
+
+		@Mock
+		private Document document;
+
+		@Mock
+		private FormData formData;
+
+		@Mock
+		private InputStream inputStream;
+
+		@DisplayName("with no representations")
+		@Nested
+		class TestWithNoRepresentations {
+			@BeforeEach
+			void mock() {
+				when(formData.getRepresentations()).thenReturn(Collections.emptyList());
+			}
+
+			@DisplayName("should return empty")
+			@Test
+			void shouldReturnEmpty() {
+				var documents = doExtract();
+
+				assertThat(documents).isEmpty();
+			}
+		}
+
+		@DisplayName("with a xml representation")
+		@Nested
+		class TestWithAXMLRepresentations {
+			@Mock
+			private IncomingFile otherRepresentation;
+
+			@Mock
+			private IncomingFile xmlRepresentation;
+
+			@Mock
+			private IncomingFile otherXMLRepresentation;
+
+			@Mock
+			private Document otherDocument;
+
+			@Mock
+			private InputStream otherInputStream;
+
+			@BeforeEach
+			void mock() {
+				when(otherRepresentation.getContentType()).thenReturn("pdf");
+				when(xmlRepresentation.getContentType()).thenReturn("xml");
+				when(otherXMLRepresentation.getContentType()).thenReturn("xml");
+				when(formData.getRepresentations()).thenReturn(List.of(otherRepresentation, xmlRepresentation, otherXMLRepresentation));
+
+				when(xmlRepresentation.getContentStream()).thenReturn(inputStream);
+				when(xmlToJavaMapsMapper.parseAsW3cDocument(inputStream)).thenReturn(document);
+
+				when(otherXMLRepresentation.getContentStream()).thenReturn(otherInputStream);
+
+			}
+
+			@DisplayName("should include all successfully parsed documents")
+			@Test
+			void shouldIncludeAllSuccessfullyParsedDocuments() {
+				when(xmlToJavaMapsMapper.parseAsW3cDocument(otherInputStream)).thenReturn(otherDocument);
+
+				var documents = doExtract();
+
+				assertThat(documents).isEqualTo(List.of(document, otherDocument));
+			}
+
+			@DisplayName("should skip documents with parse error")
+			@Test
+			void shouldSkipDocumentsWithParseError() {
+				when(xmlToJavaMapsMapper.parseAsW3cDocument(otherInputStream)).thenThrow(new TechnicalException("some error"));
+
+				var documents = doExtract();
+
+				assertThat(documents).isEqualTo(List.of(document));
+			}
+		}
+
+		private List<Document> doExtract() {
+			return adapter.streamXMLDocumentsFromRepresentations(formData).toList();
+		}
+	}
+
+	@DisplayName("is responsible")
+	@Nested
+	class TestIsResponsible {
+
+		@Mock
+		private FormData formData;
+
+		@DisplayName("should be true with namespace attribute match")
+		@Test
+		void shouldBeTrueWithNamespaceAttributeMatch() {
+
+			doReturn(Optional.of(buildXMLDocument("""
+					<myForm xmlns:t="%s">
+					</myForm>""".formatted(INTELLIFORM_TYPENAME))))
+					.when(adapter).findIntelliFormXMLRepresentation(formData);
+
+			var isResponsible = adapter.isResponsible(formData);
+
+			assertThat(isResponsible).isTrue();
+		}
+
+		@DisplayName("should be false without xml document")
+		@Test
+		void shouldBeFalseWithoutXmlDocument() {
+			doReturn(Optional.empty())
+					.when(adapter).findIntelliFormXMLRepresentation(formData);
+
+			var isResponsible = adapter.isResponsible(formData);
+
+			assertThat(isResponsible).isFalse();
+		}
+
+	}
+
+	@DisplayName("get form data entries from document")
+	@Nested
+	class TestGetFormDataEntriesFromDocument {
+
+		private static final String OTHER_VENDOR_ID = "vendorId:other";
+		private static final String MISSING_VENDOR_ID = "vendorId:missing";
+
+		@Mock
+		private Document document;
+
+		private List<IncomingFileGroup> attachments;
+
+		@BeforeEach
+		void mock() {
+			when(xmlToJavaMapsMapper.mapXmlToJavaMaps(document)).thenReturn(Map.of(
+					DOCUMENT_TEST_KEY, DOCUMENT_TEST_VALUE,
+					"Upload1", Map.of(
+							"file", Map.of("id", IncomingFileGroupTestFactory.VENDOR_ID_XXX)
+					),
+					"Upload2", Map.of(
+							"file", Map.of("id", OTHER_VENDOR_ID)
+					),
+					"Upload3", Map.of(
+							"file", Map.of("id", "representationId")
+					),
+					"NoUpload1", Map.of(
+							"file", ""
+					),
+					"NoUpload2", Map.of()
+			));
+			attachments = List.of(
+					IncomingFileGroupTestFactory.create(),
+					IncomingFileGroupTestFactory.createBuilder()
+							.name("other")
+							.files(List.of(
+									IncomingFileTestFactory.createBuilder()
+											.vendorId(MISSING_VENDOR_ID)
+											.build(),
+									IncomingFileTestFactory.createBuilder()
+											.vendorId(OTHER_VENDOR_ID)
+											.build()))
+							.build());
+
+		}
+
+		@DisplayName("should prune upload element if is an attachment")
+		@Test
+		void shouldPruneUploadElementIfIsAnAttachment() {
+			var entryKeys = obtainResidualEntryKeys();
+
+			assertThat(entryKeys).containsExactlyInAnyOrder(DOCUMENT_TEST_KEY, "Upload3", "NoUpload1", "NoUpload2");
+		}
+
+		private List<String> obtainResidualEntryKeys() {
+			return adapter.getFormDataEntriesFromDocument(document, attachments).map(Map.Entry::getKey).toList();
+		}
+	}
+
+	@DisplayName("create header map")
+	@Nested
+	class TestCreateHeaderMap {
+
+		private Document document;
+
+		@DisplayName("with full fields")
+		@Nested
+		class TestWithFullFields {
+
+			private Map<String, Object> headerMap;
+
+			@BeforeEach
+			void mock() {
+				headerMap = Stream.concat(HEADER_ATTRIBUTE_NAMES.stream(), CUSTOM_HEADER_ATTRIBUTE_NAMES.stream())
+						.collect(Collectors.toMap(name -> name, name -> LoremIpsum.getInstance().getName()));
+				document = buildXMLDocument("<root %s/>".formatted(
+								headerMap.entrySet().stream()
+										.map(entry -> "%s=\"%s\"".formatted(entry.getKey(), entry.getValue()))
+										.collect(Collectors.joining(" "))
+						)
+				);
+			}
+
+			@DisplayName("should include header field")
+			@ParameterizedTest
+			@MethodSource("headerNames")
+			void shouldIncludeAllHeaderField(String headerName) {
+				var resultHeaderMap = adapter.createHeaderMap(document);
+
+				assertThat(resultHeaderMap).containsEntry(headerName, headerMap.get(headerName));
+			}
+
+			private static Stream<Arguments> headerNames() {
+				return HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of);
+			}
+
+			@DisplayName("should include custom header field")
+			@ParameterizedTest
+			@MethodSource("customHeaderNames")
+			void shouldIncludeAllCustomHeaderField(String headerName) {
+				var resultHeaderMap = adapter.createHeaderMap(document);
+
+				assertThat(resultHeaderMap).containsEntry(headerName, headerMap.get(headerName));
+			}
+
+			private static Stream<Arguments> customHeaderNames() {
+				return CUSTOM_HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of);
+			}
+		}
+
+		@DisplayName("with empty fields")
+		@Nested
+		class TestWithEmptyFields {
+			@BeforeEach
+			void mock() {
+				document = buildXMLDocument("<root />");
+			}
+
+			@DisplayName("should include empty header field")
+			@ParameterizedTest
+			@MethodSource("headerNames")
+			void shouldIncludeAllHeaderField(String headerName) {
+				var resultHeaderMap = adapter.createHeaderMap(document);
+
+				assertThat(resultHeaderMap).containsEntry(headerName, "");
+			}
+
+			private static Stream<Arguments> headerNames() {
+				return HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of);
+			}
+
+			@DisplayName("should not include custom header field")
+			@ParameterizedTest
+			@MethodSource("customHeaderNames")
+			void shouldNotIncludeAllCustomHeaderField(String headerName) {
+				var resultHeaderMap = adapter.createHeaderMap(document);
+
+				assertThat(resultHeaderMap).doesNotContainKey(headerName);
+			}
+
+			private static Stream<Arguments> customHeaderNames() {
+				return CUSTOM_HEADER_ATTRIBUTE_NAMES.stream().map(Arguments::of);
+			}
+		}
+	}
+
+	@DisplayName("adapt by representation")
+	@Nested
+	class TestAdaptByRepresentation {
+
+		@Mock
+		private FormData formData;
+
+		@DisplayName("should throw exception without xml document")
+		@Test
+		void shouldThrowExceptionWithoutXmlDocument() {
+			doReturn(Optional.empty())
+					.when(adapter).findIntelliFormXMLRepresentation(formData);
+
+			assertThrows(TechnicalException.class, () ->
+					adapter.adaptByRepresentations(formData)
+			);
+		}
+
+		@DisplayName("with xml document")
+		@Nested
+		class TestWithXmlDocument {
+
+			@Mock
+			private IncomingFileGroup attachmentGroup;
+
+			@Mock
+			private IncomingFile xmlRepresentation;
+
+			@Mock
+			private IncomingFile otherRepresentation;
+
+			@Mock
+			private Document document;
+
+			@Mock
+			private Map<String, Object> headerFields;
+
+			private List<IncomingFileGroup> attachments;
+			private List<IncomingFile> representations;
+
+			@BeforeEach
+			void mock() {
+				attachments = List.of(attachmentGroup);
+				representations = List.of(xmlRepresentation, otherRepresentation);
+
+				when(formData.getRepresentations()).thenReturn(representations);
+				when(formData.getAttachments()).thenReturn(attachments);
+				doReturn(Optional.of(document)).when(adapter).findIntelliFormXMLRepresentation(formData);
+
+				doReturn(Map.of(DOCUMENT_TEST_KEY, DOCUMENT_TEST_VALUE).entrySet().stream())
+						.when(adapter).getFormDataEntriesFromDocument(document, attachments);
+
+				doReturn(headerFields)
+						.when(adapter).createHeaderMap(document);
+			}
+
+			@DisplayName("should have document field")
+			@Test
+			void shouldHaveDocumentField() {
+				var documentValue = obtainMappingByKey(DOCUMENT_TEST_KEY);
+
+				assertThat(documentValue).isEqualTo(DOCUMENT_TEST_VALUE);
+			}
+
+			@DisplayName("should have header field")
+			@Test
+			void shouldHaveHeaderField() {
+				var headerValue = obtainMappingByKey(HEADER_FIELD);
+
+				assertThat(headerValue).isEqualTo(headerFields);
+			}
+
+			private Object obtainMappingByKey(String key) {
+				var formDataResult = adapter.adaptByRepresentations(formData);
+
+				return formDataResult.getFormData().get(key);
+			}
+
+			@DisplayName("should have attachments")
+			@Test
+			void shouldHaveAttachments() {
+				var formDataResult = adapter.adaptByRepresentations(formData);
+
+				assertThat(formDataResult.getAttachments()).isEqualTo(attachments);
+			}
+
+			@DisplayName("should have representations")
+			@Test
+			void shouldHaveRepresentations() {
+				var formDataResult = adapter.adaptByRepresentations(formData);
+
+				assertThat(formDataResult.getRepresentations()).isEqualTo(representations);
+			}
+		}
+	}
+
+	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);
+		}
+	}
+
+}
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/JsonServiceTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonServiceTest.java
similarity index 94%
rename from intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/JsonServiceTest.java
rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonServiceTest.java
index e32bfa9c633fa6e36169d7b0674f59ab0c4ca59f..c9212b4dc604a48ae5a085da63b7ac3d62720087 100644
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/JsonServiceTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/JsonServiceTest.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.intelliform;
+package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.semantik.enginebased.afm.intelliform.JsonService;
 import lombok.SneakyThrows;
 
 class JsonServiceTest {
diff --git a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapperTest.java
similarity index 99%
rename from intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapperTest.java
rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapperTest.java
index ea6f5149f2aaba2246891aaefede93950f120a7d..37df5097b555ee8308b53570108c02024fc2745f 100644
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/XmlToJavaMapsMapperTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/XmlToJavaMapsMapperTest.java
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.eingang.intelliform;
+package de.ozgcloud.eingang.semantik.enginebased.afm.intelliform;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -31,8 +31,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
-import jakarta.xml.soap.Node;
-
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -40,6 +38,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
 
 import de.ozgcloud.common.errorhandling.TechnicalException;
 
@@ -327,4 +326,4 @@ class XmlToJavaMapsMapperTest {
 	private Map<String, Object> mapXmlToJavaMaps() {
 		return mapper.mapXmlToJavaMaps(document);
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapterTest.java
similarity index 58%
rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapperTest.java
rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapterTest.java
index dc9d2d172dde4c1e84debbc0bb270e3e3437e8cb..cccd254d34afde615debd689c4c5f73fd1c7dd5d 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormBasedMapperTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelEngineBasedSemantikAdapterTest.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.semantik.formbased;
+package de.ozgcloud.eingang.semantik.enginebased.dfoerdermittel;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.assertj.core.api.InstanceOfAssertFactories.*;
@@ -11,8 +11,6 @@ import java.util.Map;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
@@ -28,11 +26,11 @@ import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
 import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
 import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
 
-class DFoerdermittelFormBasedMapperTest {
+class DFoerdermittelEngineBasedSemantikAdapterTest {
 
 	@Spy
 	@InjectMocks
-	private DFoerdermittelFormBasedMapper mapper;
+	private DFoerdermittelEngineBasedSemantikAdapter adapter;
 
 	@Mock
 	private ServiceKontoBuildHelper serviceKontoHelper;
@@ -42,14 +40,14 @@ class DFoerdermittelFormBasedMapperTest {
 
 		@Test
 		void shouldBeTrueWithFachnachricht() {
-			var responsible = mapper.isResponsible(createWithFachnachricht());
+			var responsible = adapter.isResponsible(createWithFachnachricht());
 
 			assertThat(responsible).isTrue();
 		}
 
 		@Test
 		void shouldBeFalseForOuther() {
-			var responsible = mapper.isResponsible(FormDataTestFactory.create());
+			var responsible = adapter.isResponsible(FormDataTestFactory.create());
 
 			assertThat(responsible).isFalse();
 		}
@@ -62,21 +60,21 @@ class DFoerdermittelFormBasedMapperTest {
 		class ExtractData {
 			@Test
 			void shouldHaveFormData() {
-				var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml"));
+				var result = adapter.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml"));
 
 				assertThat(result).isNotNull();
 			}
 
 			@Test
 			void shouldHavePages() {
-				var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml"));
+				var result = adapter.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml"));
 
 				assertThat(result).containsKey("Pages");
 			}
 
 			@Test
 			void shouldHaveInboxRef() {
-				var result = mapper.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml"));
+				var result = adapter.extractFormDataFormXML(TestUtils.loadFile("xta/Beispieldatensatz_Fachnachricht.xml"));
 
 				assertThat(result).containsEntry("InboxReference", "sh/sh/4dd01647-b9d9-4775-1b50-08da3d83800a");
 			}
@@ -89,27 +87,27 @@ class DFoerdermittelFormBasedMapperTest {
 
 			@Test
 			void shouldCallExtractData() {
-				doReturn(extracted).when(mapper).extractFormDataFormXML(any());
+				doReturn(extracted).when(adapter).extractFormDataFormXML(any());
 
-				mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile());
+				adapter.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile());
 
-				verify(mapper).extractFormDataFormXML(notNull());
+				verify(adapter).extractFormDataFormXML(notNull());
 			}
 
 			@Test
 			void shouldAddMap() {
-				doReturn(extracted).when(mapper).extractFormDataFormXML(any());
+				doReturn(extracted).when(adapter).extractFormDataFormXML(any());
 
-				var result = mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile());
+				var result = adapter.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile());
 
 				assertThat(result.getFormData()).containsEntry("Fachnachricht", extracted);
 			}
 
 			@Test
 			void shouldIgnoreEmptyData() {
-				doReturn(Collections.emptyMap()).when(mapper).extractFormDataFormXML(any());
+				doReturn(Collections.emptyMap()).when(adapter).extractFormDataFormXML(any());
 
-				var result = mapper.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile());
+				var result = adapter.parseFachnachricht(createWithFachnachricht(), createFachnachrichtFile());
 
 				assertThat(result.getFormData()).doesNotContainKey("Fachnachricht");
 			}
@@ -137,27 +135,37 @@ class DFoerdermittelFormBasedMapperTest {
 	@Nested
 	class TestProcessFachnachricht {
 
-		@Captor
-		private ArgumentCaptor<Map<String, Object>> fachnachrichtCaptor;
+		@Mock
+		FormData formData0;
 
-		@Test
-		void shouldCallAddServiceKonto() {
-			var formData = DFoerdermittelFormDataTestFactory.create();
+		@Mock
+		FormData formData1;
+
+		@Mock
+		FormData formData2;
 
-			mapper.processFachnachricht(formData);
+		@Mock
+		FormData formData3;
 
-			verify(mapper).addServiceKonto(same(formData), fachnachrichtCaptor.capture());
-			assertThat(fachnachrichtCaptor.getValue()).containsAllEntriesOf(DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
+		@Mock
+		FormData formData4;
+
+		@BeforeEach
+		void mock() {
+			var formData = DFoerdermittelFormDataTestFactory.create();
+			var fachnachrichtMap = DFoerdermittelFormDataTestFactory.createFachnachrichtMap();
+			when(formData0.getFormData()).thenReturn(formData.getFormData());
+			doReturn(formData1).when(adapter).addFormName(formData0);
+			doReturn(formData2).when(adapter).addFormEngineName(formData1);
+			doReturn(formData3).when(adapter).addServiceKonto(formData2, fachnachrichtMap);
+			doReturn(formData4).when(adapter).addOrganisationsEinheitId(formData3, fachnachrichtMap);
 		}
 
 		@Test
-		void shouldCallAddOrganisationsEinheitId() {
-			var extened = DFoerdermittelFormDataTestFactory.create();
-			doReturn(extened).when(mapper).addServiceKonto(any(), any());
+		void shouldReturn() {
+			var processedFormData = adapter.processFachnachricht(formData0);
 
-			mapper.processFachnachricht(DFoerdermittelFormDataTestFactory.create());
-
-			verify(mapper).addOrganisationsEinheitId(same(extened), notNull());
+			assertThat(processedFormData).isEqualTo(formData4);
 		}
 	}
 
@@ -171,7 +179,7 @@ class DFoerdermittelFormBasedMapperTest {
 
 		@Test
 		void shouldHaveServiceKonto() {
-			var formData = mapper.addServiceKonto(DFoerdermittelFormDataTestFactory.create(),
+			var formData = adapter.addServiceKonto(DFoerdermittelFormDataTestFactory.create(),
 					DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
 
 			assertThat(formData.getHeader().getServiceKonto().getPostfachAddresses().get(0).getIdentifier())
@@ -181,7 +189,7 @@ class DFoerdermittelFormBasedMapperTest {
 
 		@Test
 		void shouldRemovePrefix() {
-			mapper.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
+			adapter.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
 
 			verify(serviceKontoHelper).buildOsiServiceKonto(DFoerdermittelFormDataTestFactory.POSTFACH_ID);
 		}
@@ -191,14 +199,14 @@ class DFoerdermittelFormBasedMapperTest {
 	class TestExtractPrefix {
 		@Test
 		void shouldRemoveAllBeforeLastSlash() {
-			var result = mapper.extractPrefix("bla/bla/bla/12345");
+			var result = adapter.extractPrefix("bla/bla/bla/12345");
 
 			assertThat(result).isEqualTo("12345");
 		}
 
 		@Test
 		void shouldBeFineWithoutSlash() {
-			var result = mapper.extractPrefix("12345");
+			var result = adapter.extractPrefix("12345");
 
 			assertThat(result).isEqualTo("12345");
 		}
@@ -208,11 +216,35 @@ class DFoerdermittelFormBasedMapperTest {
 	class TestAddOrganisationsEinheitId {
 		@Test
 		void shouldHaveOrganisationsEinheitId() {
-			var formData = mapper.addOrganisationsEinheitId(DFoerdermittelFormDataTestFactory.create(),
+			var formData = adapter.addOrganisationsEinheitId(DFoerdermittelFormDataTestFactory.create(),
 					DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
 
 			assertThat(formData.getZustaendigeStelle()).isNotNull().extracting(ZustaendigeStelle::getOrganisationseinheitenId)
 					.isEqualTo(DFoerdermittelFormDataTestFactory.ORGANISATIONS_EINHEIT_ID);
 		}
 	}
+
+	@Nested
+	class TestAddFormName {
+
+		@Test
+		void shouldHaveFormName() {
+			var formData = adapter.addFormName(DFoerdermittelFormDataTestFactory.create());
+
+			assertThat(formData.getHeader().getFormName()).isEqualTo("dFördermittelantrag");
+		}
+
+	}
+
+	@Nested
+	class TestAddFormEngineName {
+
+		@Test
+		void shouldHaveFormEngineName() {
+			var formData = adapter.addFormEngineName(DFoerdermittelFormDataTestFactory.create());
+
+			assertThat(formData.getHeader().getFormEngineName()).isEqualTo("dFördermittelantrag");
+		}
+
+	}
 }
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormDataTestFactory.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelFormDataTestFactory.java
similarity index 90%
rename from semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormDataTestFactory.java
rename to semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelFormDataTestFactory.java
index fd333fc59cea56b4bfba0b21994f5169f305a5a4..b99c66e48559d39b5c58e747c145a58dc0490363 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/DFoerdermittelFormDataTestFactory.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/dfoerdermittel/DFoerdermittelFormDataTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.semantik.formbased;
+package de.ozgcloud.eingang.semantik.enginebased.dfoerdermittel;
 
 import java.util.Map;
 
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java
index cc186d6b99d8f020ff07374682eb34f7b751b407..47c563508627226dac6341fe8d6e4b36f9062b70 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsEngineBasedAdapterITCase.java
@@ -58,9 +58,7 @@ import lombok.SneakyThrows;
 public class FormSolutionsEngineBasedAdapterITCase {
 
 	private static final String ZIP_CONTENT_TYPE = "application/zip";
-	private static final String FILE_NAME_ZIP_ATTACHMENT = "attachment-2files.zip";
-	public static final String FILE_NAME_PDF_REP = "eingang.pdf";
-	public static final String FILE_NAME_JSON_REP = "form-data.json";
+	private static final String FILE_NAME_ZIP_ATTACHMENT = "formsolutions/attachment-2files.zip";
 
 	@MockBean
 	private SemantikAdapter semantikAdapter;
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapperTest.java
deleted file mode 100644
index 56b515e083af42c3b22fc050990df4765832a277..0000000000000000000000000000000000000000
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/xta/XtaZipRepresentationsMapperTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package de.ozgcloud.eingang.semantik.enginebased.xta;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.io.InputStream;
-import java.util.List;
-import java.util.stream.IntStream;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
-import org.mockito.Spy;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
-import de.ozgcloud.eingang.semantik.common.ZipAttachmentReader;
-import lombok.SneakyThrows;
-
-class XtaZipRepresentationsMapperTest {
-
-	private static final String ZIP_CONTENT_TYPE = "application/zip";
-
-	@Spy
-	private final XtaZipRepresentationsMapper mapper = new XtaZipRepresentationsMapper();
-
-	@Nested
-	class TestExtractZipFileEctract {
-
-		@Test
-		void shouldExtractZipFiles() {
-			try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) {
-				initZipRepresentationMocks(zipAttachment);
-
-				var formData = mapper.parseFormData(createTestFormDataWithZipRepresentation());
-
-				assertThat(formData.getRepresentations()).hasSize(3);
-			}
-		}
-
-		FormData createTestFormDataWithZipRepresentation() {
-			List<IncomingFile> representations = List.of(
-					IncomingFileTestFactory.createBuilder()
-							.name("attachments.zip")
-							.contentType(ZIP_CONTENT_TYPE)
-							.build());
-
-			return FormData.builder().representations(representations).numberOfRepresentations(representations.size()).build();
-		}
-
-		@Test
-		void shouldSetRepresentationsNumber() {
-			try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) {
-				initZipRepresentationMocks(zipAttachment);
-
-				var formData = mapper.parseFormData(createTestFormDataWithZipRepresentation());
-
-				assertThat(formData.getNumberOfRepresentations()).isEqualTo(3);
-			}
-		}
-
-		@Test
-		void shouldIgnoreNonZipFiles() {
-			try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) {
-
-				var formData = mapper.parseFormData(createTestFormDataWithoutZipRepresentation());
-
-				assertThat(formData.getNumberOfRepresentations()).isEqualTo(1);
-			}
-		}
-
-		FormData createTestFormDataWithoutZipRepresentation() {
-			List<IncomingFile> representations = List.of(
-					IncomingFileTestFactory.create());
-			return FormData.builder().representations(representations).numberOfRepresentations(representations.size()).build();
-		}
-
-		@Test
-		void shouldNotDeleteOriginalZipFile() {
-			try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) {
-				initZipRepresentationMocks(zipAttachment);
-
-				var formData = mapper.parseFormData(createTestFormDataWithZipRepresentation());
-
-				assertThat(formData.getRepresentations()).map(IncomingFile::getContentType)
-						.filteredOn(e -> e.equals(XtaZipRepresentationsMapper.ZIP_CONTENT_TYPE)).hasSize(1);
-			}
-		}
-
-		@Test
-		void shouldDoNothingOnEmptyRepresentations() {
-			try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) {
-
-				var formData = mapper.parseFormData(createTestFormDataWithoutRepresentation());
-
-				assertThat(formData.getRepresentations()).isEmpty();
-			}
-		}
-
-		FormData createTestFormDataWithoutRepresentation() {
-			return FormData.builder().numberOfRepresentations(0).build();
-		}
-	}
-
-	@Test
-	void testIsZipFilePredicate() {
-
-		assertThat(XtaZipRepresentationsMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.create())).isFalse();
-		assertThat(XtaZipRepresentationsMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.createBuilder().contentType(ZIP_CONTENT_TYPE).build()))
-				.isTrue();
-	}
-
-	@SneakyThrows
-	private static void initZipRepresentationMocks(MockedStatic<ZipAttachmentReader> zipAttachmentMock) {
-		var contentEntries = IntStream.range(0, 2).boxed().map(i -> IncomingFileTestFactory.createBuilder().name(i.toString()).build()).toList();
-		ZipAttachmentReader mock = when(mock(ZipAttachmentReader.class).readContent()).thenReturn(contentEntries).getMock();
-		zipAttachmentMock.when(() -> ZipAttachmentReader.from(any(InputStream.class), any())).thenReturn(mock);
-	}
-}
diff --git a/semantik-adapter/src/test/resources/formsolutions/attachment-2files.zip b/semantik-adapter/src/test/resources/formsolutions/attachment-2files.zip
new file mode 100644
index 0000000000000000000000000000000000000000..1cd6370639e85040002e6b17df7dc2c36b877673
Binary files /dev/null and b/semantik-adapter/src/test/resources/formsolutions/attachment-2files.zip differ
diff --git a/intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml b/semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml
rename to semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDaten1.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml b/semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml
rename to semantik-adapter/src/test/resources/intelliform/EinfachesFormularZweiAnhaengeXmlDatenVerschachtelt.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml b/semantik-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml
rename to semantik-adapter/src/test/resources/intelliform/FormularSoapRequest_WithContent_XML-Daten-1.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml b/semantik-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml
rename to semantik-adapter/src/test/resources/intelliform/SimpleFormDataMapperTestFile.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml
rename to semantik-adapter/src/test/resources/intelliform/XML-Daten-1-SoapRequest.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml
rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml
rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml
rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Gewerbe_organisationseinheitenID_und_zustaendigstelle.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml b/semantik-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml
rename to semantik-adapter/src/test/resources/intelliform/XML-Daten_Strassengefaelle.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml b/semantik-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml
rename to semantik-adapter/src/test/resources/intelliform/XML-Keine_Daten.xml
diff --git a/intelliform-adapter/src/test/resources/intelliform/andererName-Daten.xml b/semantik-adapter/src/test/resources/intelliform/andererName-Daten.xml
similarity index 100%
rename from intelliform-adapter/src/test/resources/intelliform/andererName-Daten.xml
rename to semantik-adapter/src/test/resources/intelliform/andererName-Daten.xml
diff --git a/xta-adapter/pom.xml b/xta-adapter/pom.xml
index 99d04ee83d680b95aed8a21d06f39cd5bcdb179c..6557a321b925d9653ec245854de08eb44d3c9b91 100644
--- a/xta-adapter/pom.xml
+++ b/xta-adapter/pom.xml
@@ -83,6 +83,7 @@
 			<artifactId>spring-boot-configuration-processor</artifactId>
 			<optional>true</optional>
 		</dependency>
+		<!-- Test -->
 		<dependency>
 			<groupId>com.squareup.okio</groupId>
 			<artifactId>okio</artifactId>
@@ -95,6 +96,12 @@
 			<version>${mockwebserver.version}</version>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.eingang</groupId>
+			<artifactId>common</artifactId>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 	
 	<build>
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageData.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageData.java
new file mode 100644
index 0000000000000000000000000000000000000000..432b06c5273798eb5bf67ff0666dea40211c69ad
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageData.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.eingang.xdomea;
+
+import java.util.List;
+
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import lombok.Builder;
+import lombok.Singular;
+
+@Builder
+public record XdomeaMessageData(
+		IncomingFile metadataFile,
+		List<IncomingFile> representations,
+		@Singular
+		List<IncomingFileGroup> attachments
+) {
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6d9f6836b5ef0d26087356de2545d512683b863
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapper.java
@@ -0,0 +1,111 @@
+package de.ozgcloud.eingang.xdomea;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+@RequiredArgsConstructor
+public class XdomeaMessageDataMapper {
+	static final String XDOMEA_0201_XML_FILE_NAME_SUFFIX = "_Geschaeftsgang.Geschaeftsgang.0201.xml";
+	static final String ATTACHMENT_GROUP_NAME = "Dokument";
+
+	private final XdomeaXMLValueReader valueReader;
+
+	public XdomeaMessageData mapIncomingFilesToXdomeaMessageData(List<IncomingFile> incomingFileList) {
+		var xdomeaXMLFile = findXdomeaXMLFile(incomingFileList);
+		var representationFileNames = valueReader.readRepresentationFileNames(xdomeaXMLFile);
+		var attachmentFileNames = getFileNamesExcluding(
+				incomingFileList,
+				Stream.concat(Stream.of(xdomeaXMLFile.getName()), representationFileNames.stream())
+		);
+
+		var fileNameToFileMap = createFileNameToIncomingFileMap(incomingFileList);
+		return XdomeaMessageData.builder()
+				.metadataFile(xdomeaXMLFile)
+				.representations(getRepresentations(representationFileNames, fileNameToFileMap))
+				.attachments(getAttachments(attachmentFileNames, fileNameToFileMap))
+				.build();
+	}
+
+	private Map<String, IncomingFile> createFileNameToIncomingFileMap(List<IncomingFile> incomingFileList) {
+		return incomingFileList.stream()
+				.collect(Collectors.toMap(IncomingFile::getName, file -> file));
+	}
+
+	private Stream<String> getFileNamesExcluding(List<IncomingFile> incomingFileList, Stream<String> excludedFileNames) {
+		return dropNames(
+				incomingFileList.stream().map(IncomingFile::getName),
+				excludedFileNames.collect(Collectors.toSet())
+		);
+	}
+
+	private List<IncomingFile> getRepresentations(List<String> representationFileNames, Map<String, IncomingFile> fileNameToFileMap) {
+		return getFilesByName(
+				movePrimaryRepresentationFileNameToFirstPosition(representationFileNames),
+				fileNameToFileMap
+		);
+	}
+
+	private List<IncomingFileGroup> getAttachments(Stream<String> attachmentFileNames, Map<String, IncomingFile> fileNameToFileMap) {
+		return Stream.of(IncomingFileGroup.builder()
+						.name(ATTACHMENT_GROUP_NAME)
+						.files(
+								getFilesByName(
+										attachmentFileNames,
+										fileNameToFileMap
+								)
+						)
+						.build())
+				// Do not include empty attachment group
+				.filter(group -> !group.getFiles().isEmpty())
+				.toList();
+	}
+
+	private Stream<String> movePrimaryRepresentationFileNameToFirstPosition(List<String> representationFileNames) {
+		var primaryRepresentationFileName = findPrimaryRepresentationName(representationFileNames);
+		return Stream.concat(
+				Stream.of(primaryRepresentationFileName),
+				dropNames(representationFileNames.stream(), Set.of(primaryRepresentationFileName))
+		);
+	}
+
+	private List<IncomingFile> getFilesByName(Stream<String> names, Map<String, IncomingFile> fileNameToFileMap) {
+		return names.map(fileNameToFileMap::get).toList();
+	}
+
+	private Stream<String> dropNames(Stream<String> names, Set<String> namesToDrop) {
+		return names.filter(name -> !namesToDrop.contains(name));
+	}
+
+	String findPrimaryRepresentationName(List<String> representationFileNames) {
+		var xmlFileNames = representationFileNames.stream()
+				.filter(name -> name.endsWith(".xml"))
+				.toList();
+		if (xmlFileNames.isEmpty()) {
+			throw new TechnicalException("No xml representation file name found!");
+		} else if (xmlFileNames.size() > 1) {
+			LOG.warn("There is more than one xml representations. Choosing the first of {}.", xmlFileNames.size());
+		}
+		return xmlFileNames.getFirst();
+	}
+
+	IncomingFile findXdomeaXMLFile(List<IncomingFile> incomingFileList) {
+		return incomingFileList.stream()
+				.filter(file -> file.getName().endsWith(XDOMEA_0201_XML_FILE_NAME_SUFFIX))
+				.findFirst()
+				.orElseThrow(() -> new TechnicalException("Primary xdomea xml representation not found!"));
+	}
+
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0fc982a33fc939726023ff751d36873e811b105
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java
@@ -0,0 +1,60 @@
+package de.ozgcloud.eingang.xdomea;
+
+import static de.ozgcloud.eingang.common.xml.XMLHelper.*;
+
+import java.util.List;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.xml.XMLHelper;
+
+@Component
+public class XdomeaXMLValueReader {
+
+	private static final String DATEINAME_NODE_QUERY_STRING = "//Hauptobjekt//Dateiname";
+	private static final XPathExpression DATEINAME_NODE_QUERY = compileXPathExpression(DATEINAME_NODE_QUERY_STRING);
+
+	public List<String> readRepresentationFileNames(IncomingFile xdomeaXMLFile) {
+		return getTextsFromNodes(
+				queryDateinameNodeList(
+						XMLHelper.parseDocument(xdomeaXMLFile)
+								.getDocumentElement()
+				)
+		);
+	}
+
+	private NodeList queryDateinameNodeList(Element contextElement) {
+		try {
+			return (NodeList) DATEINAME_NODE_QUERY
+					.evaluate(
+							contextElement,
+							XPathConstants.NODESET
+					);
+		} catch (XPathExpressionException e) {
+			throw new TechnicalException("Failed to execute xpath search!", e);
+		}
+	}
+
+	private List<String> getTextsFromNodes(NodeList nodeList) {
+		return streamNodeList(nodeList)
+				.map(Node::getTextContent)
+				.toList();
+	}
+
+	private Stream<Node> streamNodeList(NodeList nodeList) {
+		return IntStream.range(0, nodeList.getLength())
+				.mapToObj(nodeList::item);
+	}
+
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaApplicationConfiguration.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaApplicationConfiguration.java
deleted file mode 100644
index 2b85133aa7ae8573b513cf189c4adeb3e12f96bf..0000000000000000000000000000000000000000
--- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaApplicationConfiguration.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.ozgcloud.eingang.xta;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import de.ozgcloud.eingang.semantik.enginebased.xta.XtaEngineBasedAdapter;
-
-@Configuration
-class XtaApplicationConfiguration {
-
-	@Bean
-	XtaEngineBasedAdapter engineBasedAdapter() {
-		return new XtaEngineBasedAdapter();
-	}
-}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2a5d411e664c3a06141e06b7798f07f8bb603ae
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das
+ * Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
+ * Zentrales IT-Management
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+
+package de.ozgcloud.eingang.xta;
+
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.zip.ZipAttachmentReader;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+@Log4j2
+@Component
+public class XtaIncomingFilesMapper {
+	public static final String ZIP_CONTENT_TYPE = "application/zip";
+	static final Predicate<IncomingFile> IS_ZIP_FILE = contentType -> ZIP_CONTENT_TYPE.equals(contentType.getContentType());
+
+	List<IncomingFile> toIncomingFiles(Collection<XtaFile> messageFiles) {
+		if (Objects.nonNull(messageFiles)) {
+			return messageFiles.stream()
+					.map(this::toIncomingFile)
+					.flatMap(this::extractZip)
+					.toList();
+		}
+		return List.of();
+	}
+
+	IncomingFile toIncomingFile(XtaFile messageFile) {
+		if (!messageFile.contentType().equals(ZIP_CONTENT_TYPE)) {
+			LOG.warn("Expected XTA messageFile to be of content type " + ZIP_CONTENT_TYPE + ". Instead was " + messageFile.contentType());
+		}
+		return IncomingFile.builder()
+				.name(messageFile.name())
+				.contentType(messageFile.contentType())
+				.file(messageFile.file())
+				.size(messageFile.file().length())
+				.build();
+	}
+
+	Stream<IncomingFile> extractZip(IncomingFile incomingFile) {
+		if (IS_ZIP_FILE.test(incomingFile)) {
+			try {
+				List<IncomingFile> extractedZips = ZipAttachmentReader.from(incomingFile.getContentStream(), incomingFile.getName()).readContent();
+				return extractedZips.stream();
+			} catch (RuntimeException e) {
+				LOG.error("Cannot read source ZIP. Not extracting file", e);
+				return Stream.of(incomingFile);
+			}
+		}
+		else {
+			return Stream.of(incomingFile);
+		}
+	}
+}
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 f2e05fc7684fe33d1db3dd42ae46f1f044f23ef8..af561ff948a92bee781a4745cd9b98af4ece0c8e 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,50 +1,51 @@
 package de.ozgcloud.eingang.xta;
 
-import java.util.Objects;
+import java.util.List;
+import java.util.stream.Stream;
 
+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.IncomingFile;
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageData;
 
-@Mapper
+@Mapper(imports = FilesMapperHelper.class)
 interface XtaMessageMapper {
+	int VORGANG_NUMMER_SUFFIX_LENGTH = 4;
 
 	@Mapping(target = "antragsteller", ignore = true)
-	@Mapping(target = "attachment", ignore = true)
-	@Mapping(target = "attachments", ignore = true)
 	@Mapping(target = "formData", ignore = true)
 	@Mapping(target = "id", ignore = true)
-	@Mapping(target = "numberOfAttachments", ignore = true)
-	@Mapping(target = "numberOfRepresentations", constant = "1")
-	@Mapping(target = "representation", ignore = true)
-	@Mapping(target = "representations", source = "messageFiles")
 	@Mapping(target = "zustaendigeStelle", ignore = true)
 	@Mapping(target = "header", source = "metaData")
-	FormData toFormData(XtaMessage message);
+	@Mapping(target = "numberOfAttachments", expression = "java(FilesMapperHelper.countAttachedFiles(xdomeaMessageData.attachments()))")
+	@Mapping(target = "numberOfRepresentations", dependsOn = "representations", expression = "java(getRepresentations(xdomeaMessageData).size())")
+	@Mapping(target = "representations", source = "xdomeaMessageData")
+	@Mapping(target = "representation", ignore = true)
+	@Mapping(target = "attachment", ignore = true)
+	FormData toFormData(XdomeaMessageData xdomeaMessageData, XtaMessageMetaData metaData, @Context VorgangNummerSupplier vorgangNummerSupplier);
+
+	default List<IncomingFile> getRepresentations(XdomeaMessageData xdomeaMessageData) {
+		return Stream.concat(
+				Stream.of(xdomeaMessageData.metadataFile()),
+				xdomeaMessageData.representations().stream()
+		).toList();
+	}
 
-	@Mapping(target = "formEngineName", ignore = true)
 	@Mapping(target = "formId", source = "messageType")
 	@Mapping(target = "requestId", source = "messageId")
+	@Mapping(target = "vorgangNummer", expression = "java(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH))")
 	@Mapping(target = "serviceKonto", ignore = true)
 	@Mapping(target = "createdAt", source = "origin")
 	@Mapping(target = "sender", constant = "XTA")
-	@Mapping(target = "formName", constant = "dFördermittelantrag")
-	FormHeader formHeaderFromMetaData(XtaMessageMetaData metaData);
-
-	default IncomingFile toIncomingFile(XtaFile messageFile) {
-		if (Objects.nonNull(messageFile)) {
-			return IncomingFile.builder()
-					.name(messageFile.name())
-					.contentType("application/zip")
-					.file(messageFile.file())
-					.size(messageFile.file().length())
-					.build();
-		}
-		return null;
-	}
+	@Mapping(target = "formName", ignore = true)
+	@Mapping(target = "formEngineName", ignore = true)
+	FormHeader formHeaderFromMetaData(XtaMessageMetaData metaData, @Context VorgangNummerSupplier vorgangNummerSupplier);
 
 	default String fromId(XtaMessageId id) {
 		return id.toString();
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 5da39aab1d30059a0e4577686a7427bc860f6278..4f59251706db33e1fe5d24ce333fb7f3a255a5a3 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
@@ -12,6 +12,9 @@ import java.util.stream.Stream;
 import javax.xml.namespace.QName;
 import javax.xml.transform.TransformerException;
 
+import jakarta.validation.Valid;
+import jakarta.xml.bind.JAXBElement;
+
 import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -44,8 +47,6 @@ import eu.osci.ws._2008._05.transport.MsgSelector;
 import eu.osci.ws._2008._05.transport.MsgStatusListType;
 import eu.osci.ws._2008._05.transport.ObjectFactory;
 import eu.osci.ws._2014._10.transport.MessageMetaData;
-import jakarta.validation.Valid;
-import jakarta.xml.bind.JAXBElement;
 import lombok.NonNull;
 import lombok.extern.log4j.Log4j2;
 
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 9e60b84b7ac4ba0dafc491ae1d80742a4d002d58..2341fbf6dc93899cb0c195ee6f09be52266c5c81 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
@@ -4,13 +4,14 @@ import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.FormHeader;
-import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
 import lombok.NonNull;
 import lombok.extern.log4j.Log4j2;
 
@@ -18,8 +19,7 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 class XtaService {
 
-	static final String DFOERDERMITTELANTRAG_MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201";
-	static final int VORGANG_NUMMER_SUFFIX_LENGTH = 4;
+	static final String XDOMEA_0201_MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201";
 
 	@Autowired
 	private XtaRemoteService remoteService;
@@ -27,9 +27,13 @@ class XtaService {
 	private XtaMessageMapper mapper;
 	@Autowired
 	private VorgangNummerSupplier vorgangNummerSupplier;
+	@Autowired
+	private XdomeaMessageDataMapper xdomeaMessageDataMapper;
+	@Autowired
+	private XtaIncomingFilesMapper xtaIncomingFilesMapper;
 
 	public Stream<FormData> getMessages() {
-		return createXtaMessageStream().filter(this::filterByMessageType).map(this::getFormData);
+		return createXtaMessageStream().filter(this::isSupportedMessageType).map(this::getFormData);
 	}
 
 	Stream<XtaMessageMetaData> createXtaMessageStream() {
@@ -37,10 +41,8 @@ class XtaService {
 		return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
 	}
 
-	// filter criteria for dFoerdermittelantrag
-	// https://jira.mgm-tp.com/jira/browse/OZG-3659
-	boolean filterByMessageType(XtaMessageMetaData metaData) {
-		if (StringUtils.equals(metaData.getMessageType(), DFOERDERMITTELANTRAG_MESSAGE_TYPE)) {
+	boolean isSupportedMessageType(XtaMessageMetaData metaData) {
+		if (StringUtils.equals(metaData.getMessageType(), XDOMEA_0201_MESSAGE_TYPE)) {
 			return true;
 		}
 
@@ -50,16 +52,10 @@ class XtaService {
 
 	public FormData getFormData(@NonNull XtaMessageMetaData metaData) {
 		var msg = remoteService.getMessage(metaData.getMessageId());
-		var formData = mapper.toFormData(msg.toBuilder().metaData(metaData).build());
-		return updateHeader(formData);
-	}
-
-	FormData updateHeader(FormData formData) {
-		return formData.toBuilder().header(setVorgangNummer(formData.getHeader())).build();
-	}
+		var incomingFiles = xtaIncomingFilesMapper.toIncomingFiles(msg.getMessageFiles());
+		var xdomeaMessageData = xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles);
 
-	FormHeader setVorgangNummer(FormHeader formHeader) {
-		return formHeader.toBuilder().vorgangNummer(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH)).build();
+		return mapper.toFormData(xdomeaMessageData, metaData, vorgangNummerSupplier);
 	}
 
 	public void acknowledgeReceive(@NonNull XtaMessageId messageId) {
diff --git a/xta-adapter/src/main/resources/soapUiProjekt/XTA.zip b/xta-adapter/src/main/resources/soapUiProjekt/XTA.zip
new file mode 100644
index 0000000000000000000000000000000000000000..8e60ba0bf6dab53dd22cad0cfd6f5372dae292e2
Binary files /dev/null and b/xta-adapter/src/main/resources/soapUiProjekt/XTA.zip differ
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b061b1590bae4d357d79eec4f5eea866b314ae34
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataMapperTest.java
@@ -0,0 +1,179 @@
+package de.ozgcloud.eingang.xdomea;
+
+import static de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+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.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
+
+class XdomeaMessageDataMapperTest {
+
+	@Spy
+	@InjectMocks
+	XdomeaMessageDataMapper fileClassifier;
+
+	@Mock
+	private XdomeaXMLValueReader valueReader;
+
+	@DisplayName("find Xdomea XML file")
+	@Nested
+	class TestFindXdomeaXmlFile {
+
+		private static final String FILE_NAME_WITHOUT_SUFFIX = "some-file-name.xml";
+		private static final String FILE_NAME_WITH_SUFFIX = "some-file-name" + XDOMEA_0201_XML_FILE_NAME_SUFFIX;
+
+		@DisplayName("should throw if not found")
+		@Test
+		void shouldThrowIfNotFound() {
+			var incomingFilesWithout = List.of(IncomingFileTestFactory.createWithName(FILE_NAME_WITHOUT_SUFFIX));
+
+			assertThatThrownBy(() -> fileClassifier.findXdomeaXMLFile(incomingFilesWithout))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		@DisplayName("should return if found")
+		@Test
+		void shouldReturnIfFound() {
+			var targetIncomingFile = IncomingFileTestFactory.createWithName(FILE_NAME_WITH_SUFFIX);
+			var incomingFilesWith = List.of(
+					IncomingFileTestFactory.createWithName(FILE_NAME_WITHOUT_SUFFIX),
+					targetIncomingFile
+			);
+
+			var primaryRepresentation = fileClassifier.findXdomeaXMLFile(incomingFilesWith);
+
+			assertThat(primaryRepresentation).isEqualTo(targetIncomingFile);
+		}
+	}
+
+	@DisplayName("find primary representation name")
+	@Nested
+	class TestFindPrimaryRepresentationName {
+		private static final String FILE_NAME_WITHOUT_XML_SUFFIX = "some-file-name.pdf";
+		private static final String FILE_NAME_WITHOUT_XML_SUFFIX2 = "some-file-name.xml.pdf";
+		private static final String FILE_NAME_WITH_XML_SUFFIX = "some-file-name.xml";
+		private static final String FILE_NAME_WITH_XML_SUFFIX2 = "some-file-name.pdf.xml";
+
+		@DisplayName("should throw if no xml suffix")
+		@Test
+		void shouldThrowIfNoXmlSuffix() {
+			var listWithoutSuffix = List.of(FILE_NAME_WITHOUT_XML_SUFFIX, FILE_NAME_WITHOUT_XML_SUFFIX2);
+
+			assertThrows(TechnicalException.class, () -> fileClassifier.findPrimaryRepresentationName(listWithoutSuffix));
+		}
+
+		@DisplayName("should return first with xml suffix")
+		@Test
+		void shouldReturnFirstWithXmlSuffix() {
+			var listWithSuffix = List.of(FILE_NAME_WITHOUT_XML_SUFFIX, FILE_NAME_WITH_XML_SUFFIX, FILE_NAME_WITHOUT_XML_SUFFIX2,
+					FILE_NAME_WITH_XML_SUFFIX2);
+
+			var fileName = fileClassifier.findPrimaryRepresentationName(listWithSuffix);
+
+			assertThat(fileName).isEqualTo(FILE_NAME_WITH_XML_SUFFIX);
+		}
+	}
+
+	@DisplayName("classify attachments and representations")
+	@Nested
+	class TestClassifyAttachmentsAndRepresentations {
+
+		private static final String XDOMEA_XML_NAME = "xdomea.xml";
+		private static final String REPR_XML_NAME = "repr.xml";
+		private static final String REPR_PDF_NAME = "repr.pdf";
+		private static final String ATTATCHMENT_XML_NAME = "att.xml";
+		private static final String ATTATCHMENT_PNG_NAME = "att.png";
+		private static final String ATTATCHMENT_PDF_NAME = "att.pdf";
+
+		@Mock
+		private IncomingFile xdomeaXMLFile;
+
+		private List<IncomingFile> incomingFileList;
+
+		@BeforeEach
+		void mock() {
+			incomingFileList = Stream.of(
+							XDOMEA_XML_NAME,
+							REPR_XML_NAME,
+							REPR_PDF_NAME,
+							ATTATCHMENT_XML_NAME,
+							ATTATCHMENT_PNG_NAME,
+							ATTATCHMENT_PDF_NAME
+					)
+					.map(IncomingFileTestFactory::createWithName)
+					.toList();
+			doReturn(xdomeaXMLFile).when(fileClassifier).findXdomeaXMLFile(incomingFileList);
+
+			when(xdomeaXMLFile.getName()).thenReturn(XDOMEA_XML_NAME);
+
+			var representationFileNames = List.of(REPR_PDF_NAME, REPR_XML_NAME);
+			when(valueReader.readRepresentationFileNames(xdomeaXMLFile)).thenReturn(representationFileNames);
+			doReturn(REPR_XML_NAME).when(fileClassifier).findPrimaryRepresentationName(representationFileNames);
+		}
+
+		@DisplayName("should contain xdomea metadata file")
+		@Test
+		void shouldContainXdomeaMetadataFile() {
+			var classification = doClassify();
+
+			var primaryDocument = classification.metadataFile();
+
+			assertThat(primaryDocument.getName()).isEqualTo(XDOMEA_XML_NAME);
+		}
+
+		@DisplayName("should contain representations")
+		@Test
+		void shouldContainRepresentations() {
+			var classification = doClassify();
+
+			var resultRepresentationFileNames = classification.representations().stream()
+					.map(IncomingFile::getName)
+					.toList();
+			// Expect that the primary representation xml file is move to the first position
+			assertThat(resultRepresentationFileNames).isEqualTo(List.of(REPR_XML_NAME, REPR_PDF_NAME));
+		}
+
+		@DisplayName("should contain attachments")
+		@Test
+		void shouldContainAttachments() {
+			var classification = doClassify();
+
+			var resultAttachmentFileNames = classification.attachments()
+					.getFirst()
+					.getFiles().stream()
+					.map(IncomingFile::getName)
+					.toList();
+			assertThat(resultAttachmentFileNames).isEqualTo(List.of(ATTATCHMENT_XML_NAME, ATTATCHMENT_PNG_NAME, ATTATCHMENT_PDF_NAME));
+		}
+
+		@DisplayName("should have attachment group name")
+		@Test
+		void shouldHaveAttachmentGroupName() {
+			var classification = doClassify();
+
+			var resultAttachmentGroupName = classification.attachments()
+					.getFirst()
+					.getName();
+			assertThat(resultAttachmentGroupName).isEqualTo(ATTACHMENT_GROUP_NAME);
+		}
+
+		private XdomeaMessageData doClassify() {
+			return fileClassifier.mapIncomingFilesToXdomeaMessageData(incomingFileList);
+		}
+	}
+
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..90a659b8ddddb9cbef12e8c54da9f33ee213ab74
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaMessageDataTestFactory.java
@@ -0,0 +1,19 @@
+package de.ozgcloud.eingang.xdomea;
+
+import java.util.List;
+
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
+
+public class XdomeaMessageDataTestFactory {
+	public static XdomeaMessageData create() {
+		return createBuilder().build();
+	}
+
+	public static XdomeaMessageData.XdomeaMessageDataBuilder createBuilder() {
+		return XdomeaMessageData.builder()
+				.metadataFile(IncomingFileTestFactory.createBuilder().name("xdomea-primary-document.xml").build())
+				.representations(List.of(IncomingFileTestFactory.create()))
+				.attachment(IncomingFileGroup.builder().file(IncomingFileTestFactory.create()).build());
+	}
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..01f474a3112f356f02d19157029a87cc636c441d
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReaderTest.java
@@ -0,0 +1,58 @@
+package de.ozgcloud.eingang.xdomea;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.common.test.TestUtils;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import lombok.SneakyThrows;
+
+class XdomeaXMLValueReaderTest {
+	private static final String XML_FILE_NAME = "file.xml";
+	private static final String PDF_FILE_NAME = "file.pdf";
+
+	@Spy
+	@InjectMocks
+	private XdomeaXMLValueReader valueReader;
+
+	@DisplayName("read representation file names")
+	@Nested
+	class TestReadRepresentationFileNames {
+
+		@Mock
+		IncomingFile incomingXmlFile;
+
+		@DisplayName("should find 'Dateiname' elements in MSR mantelantrag")
+		@ParameterizedTest
+		@ValueSource(strings = {
+				"xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml",
+				"xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml"
+		})
+		@SneakyThrows
+		void shouldFindDateinameElements(String antragXMLFilename) {
+			var xmlString = TestUtils.loadTextFile(
+					antragXMLFilename,
+					XML_FILE_NAME,
+					PDF_FILE_NAME);
+			when(incomingXmlFile.getContentStream()).thenReturn(IOUtils.toInputStream(xmlString, StandardCharsets.UTF_8));
+
+			var names = valueReader.readRepresentationFileNames(incomingXmlFile);
+
+			assertThat(names).isEqualTo(List.of(XML_FILE_NAME, PDF_FILE_NAME));
+		}
+
+	}
+
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java
index db83159ccffc9185959569982fc9d09c7479a6fe..acd02b8efce3f09542c8dc5c748850027ad27072 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java
@@ -1,11 +1,12 @@
 package de.ozgcloud.eingang.xta;
 
 import de.ozgcloud.eingang.common.formdata.FormHeader;
-import de.ozgcloud.eingang.common.formdata.FormHeader.FormHeaderBuilder;;
+import de.ozgcloud.eingang.common.formdata.FormHeader.FormHeaderBuilder;
 
 public class FormHeaderTestFactory {
 
-	private static final String FORM_NAME = "dFördermittelantrag";
+	private static final String FORM_NAME = "xdomea";
+	static final String VORGANGNUMMER = "vorgangNummer";
 
 	static FormHeader create() {
 		return createBuilder().build();
@@ -15,6 +16,7 @@ public class FormHeaderTestFactory {
 		return FormHeader.builder()
 				.sender("XTA")
 				.requestId(XtaMessageTestFactory.MESSAGE_ID.toString())
+				.vorgangNummer(VORGANGNUMMER)
 				.formName(FORM_NAME)
 				.formId(XtaMessageMetaDataTestFactory.MESSAGE_TYPE)
 				.createdAt(XtaMessageMetaDataTestFactory.ORIGIN);
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java
index 59bddcf63df7c9135a753a6ee4aab49a375bd087..8e2d830f342905d66d07dca69cd304b92bef142c 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaApplicationTest.java
@@ -1,32 +1,21 @@
 package de.ozgcloud.eingang.xta;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
 import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.ActiveProfiles;
 
 import de.ozgcloud.eingang.Application;
-import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
-import de.ozgcloud.eingang.semantik.enginebased.xta.XtaEngineBasedAdapter;
 
 @ActiveProfiles({ "local", "itcase" })
 @SpringBootTest(classes = Application.class)
 class XtaApplicationTest {
 
-	@Autowired
-	private EngineBasedSemantikAdapter engineBasedAdapter;
-
 	@Test
 	void startup() {
 		// should start without exception;
 		assertTrue(true);
 	}
 
-	@Test
-	void shouldHaveEngineBasedAdapter() {
-		assertThat(engineBasedAdapter).isInstanceOf(XtaEngineBasedAdapter.class);
-	}
 }
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java
index f6eaca430bafa55daa30defef2ca846a3f91a07a..5512656128e6245be33f1f274e87f536637914ca 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaFileTestFactory.java
@@ -13,18 +13,22 @@ class XtaFileTestFactory {
 
 	static final String NAME = "Test_File";
 	static final String CONTENT = "slkafj3jifsdasx";
+	static final String ZIP_CONTENT_TYPE = "application/zip";
 
 	static XtaFile create() {
 		return createBuilder().build();
 	}
 
 	static XtaFile.XtaFileBuilder createBuilder() {
-		return XtaFile.builder().name(NAME).file(createFile());
+		return XtaFile.builder()
+				.name(NAME)
+				.contentType(ZIP_CONTENT_TYPE)
+				.file(createFile());
 	}
 
 	@SneakyThrows
 	private static File createFile() {
-		File tFile = File.createTempFile("test", "txt");
+		File tFile = File.createTempFile("test", "zip");
 		tFile.deleteOnExit();
 
 		FileUtils.write(tFile, CONTENT, StandardCharsets.UTF_8);
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java
index beb10f64917e4923553562d5ffa19298e4a58db8..8f22e393ae6f75b7bf19a48b6c682e8476899b6e 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java
@@ -44,7 +44,8 @@ class XtaITCase {
 		when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(
 				XtaMessageTestFactory.createBuilder()
 						.clearMessageFiles()
-						.messageFile(XtaFileTestFactory.withFileContent(TestUtils.loadFile("test_content.zip"), "test_content.zip"))
+						.messageFile(XtaFileTestFactory.withFileContent(TestUtils.loadFile("xdomea/dfoerdermittel_without_anlage.zip"),
+								"dfoerdermittel_without_anlage.zip"))
 						.build());
 	}
 
@@ -63,12 +64,21 @@ class XtaITCase {
 	}
 
 	@Test
-	void shouldSend4Representations() {
+	void shouldSend3Representations() {
 		runner.onApplicationEvent(null);
 
 		verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), any(), any());
-		assertThat(formDataCaptor.getValue().getNumberOfRepresentations()).isEqualTo(4);
-		assertThat(formDataCaptor.getValue().getRepresentations()).hasSize(4);
+		assertThat(formDataCaptor.getValue().getRepresentations()).hasSize(3);
+		assertThat(formDataCaptor.getValue().getNumberOfRepresentations()).isEqualTo(3);
+	}
+
+	@Test
+	void shouldSendNoAttachments() {
+		runner.onApplicationEvent(null);
+
+		verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), any(), any());
+		assertThat(formDataCaptor.getValue().getAttachments()).isEmpty();
+		assertThat(formDataCaptor.getValue().getNumberOfAttachments()).isZero();
 	}
 
 	@Test
@@ -115,4 +125,4 @@ class ActivateXTARunnerConfig {
 	XtaRunner xtaRunner() {
 		return new XtaRunner();
 	}
-}
\ No newline at end of file
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..da3cdcceeefb8b0f298fb7166bd200fc28b335bc
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das
+ * Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
+ * Zentrales IT-Management
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+
+package de.ozgcloud.eingang.xta;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
+import de.ozgcloud.eingang.common.zip.ZipAttachmentReader;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+class XtaIncomingFilesMapperTest {
+	@Spy
+	private XtaIncomingFilesMapper mapper = new XtaIncomingFilesMapper();
+
+	private static final String ZIP_CONTENT_TYPE = "application/zip";
+
+	@Nested
+	class TestToIncomingFiles {
+
+		@Test
+		void shouldMapToIncomingFiles() {
+			var xtaFile = XtaFileTestFactory.create();
+			var incomingFile = IncomingFileTestFactory.create();
+			when(mapper.toIncomingFile(xtaFile)).thenReturn(incomingFile);
+			when(mapper.extractZip(incomingFile)).thenAnswer((x) -> Stream.of(incomingFile));
+
+			mapper.toIncomingFiles(List.of(xtaFile, xtaFile));
+
+			inOrder(mapper).verify(mapper, calls(2)).toIncomingFile(xtaFile);
+			inOrder(mapper).verify(mapper, calls(2)).extractZip(incomingFile);
+		}
+
+		@Test
+		void shouldHandleMissingMessageFile() {
+			var fileGroup = mapper.toIncomingFiles(null);
+
+			assertThat(fileGroup).isEmpty();
+		}
+	}
+
+	@Nested
+	class ToIncomingFile {
+		@Test
+		void shouldHaveMessageFile() {
+			var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
+
+			assertThat(inFile.getContentStream()).isNotNull();
+		}
+
+		@Test
+		void shouldHaveFileName() {
+			var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
+
+			assertThat(inFile.getName()).isEqualTo(XtaFileTestFactory.NAME);
+		}
+
+		@Test
+		void shouldHaveZipContentType() {
+			var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
+
+			assertThat(inFile.getContentType()).isEqualTo(XtaFileTestFactory.ZIP_CONTENT_TYPE);
+		}
+
+		@Test
+		void shouldHaveSize() {
+			var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
+
+			assertThat(inFile.getSize()).isEqualTo(XtaFileTestFactory.CONTENT.length());
+		}
+	}
+
+	@Nested
+	class TestExtractZip {
+
+		@Test
+		void shouldExtractZipFiles() {
+			try (var zipAttachment = Mockito.mockStatic(ZipAttachmentReader.class)) {
+				var zipAttachmentReaderMock = initZipRepresentationMocks(zipAttachment);
+
+				var extractedFiles = mapper.extractZip(createTestIncomingFile()).toList();
+
+				verify(zipAttachmentReaderMock).readContent();
+				assertThat(extractedFiles).hasSize(2);
+			}
+		}
+
+		IncomingFile createTestIncomingFile() {
+			return IncomingFileTestFactory.createBuilder()
+							.name("attachments.zip")
+							.contentType(ZIP_CONTENT_TYPE)
+							.build();
+		}
+
+		@Test
+		void shouldIgnoreNonZipFiles() {
+			var incomingFile = IncomingFileTestFactory.create();
+
+			var extractedFiles = mapper.extractZip(incomingFile).toList();
+
+			assertThat(extractedFiles).containsExactly(incomingFile);
+		}
+	}
+
+	@Test
+	void testIsZipFilePredicate() {
+		assertThat(XtaIncomingFilesMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.create())).isFalse();
+		assertThat(XtaIncomingFilesMapper.IS_ZIP_FILE.test(IncomingFileTestFactory.createBuilder().contentType(ZIP_CONTENT_TYPE).build()))
+				.isTrue();
+	}
+
+	@SneakyThrows
+	private static ZipAttachmentReader initZipRepresentationMocks(MockedStatic<ZipAttachmentReader> zipAttachmentMock) {
+		var contentEntries = IntStream.range(0, 2).boxed().map(i -> IncomingFileTestFactory.createBuilder().name(i.toString()).build()).toList();
+		ZipAttachmentReader mock = when(mock(ZipAttachmentReader.class).readContent()).thenReturn(contentEntries).getMock();
+		zipAttachmentMock.when(() -> ZipAttachmentReader.from(any(InputStream.class), any())).thenReturn(mock);
+		return mock;
+	}
+}
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 7655eb0d5a3253758a940dba565a2bedb3c6c8fe..b9bcda822a302872474e1c4341cbe08b11675b99 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
@@ -1,95 +1,81 @@
 package de.ozgcloud.eingang.xta;
 
+import static de.ozgcloud.eingang.xta.XtaMessageMapper.*;
 import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
+import org.mockito.Mock;
 import org.mockito.Spy;
 
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageData;
+
 class XtaMessageMapperTest {
 
 	@Spy
 	@InjectMocks
 	private XtaMessageMapper mapper = Mappers.getMapper(XtaMessageMapper.class);
 
+	@Mock
+	private VorgangNummerSupplier vorgangNummerSupplier;
+
 	@Nested
 	class TestToFormData {
 
-		@Test
-		void shouldMapAllToForm() {
-			var formData = mapper.toFormData(XtaMessageTestFactory.create());
+		private XtaMessageMetaData xtaMessageMetaData;
+		private XdomeaMessageData xdomeaMessageData;
 
-			assertThat(formData).usingRecursiveComparison().ignoringFields("id", "representations")
-					.isEqualTo(FormDataTestFactory.create());
+		@BeforeEach
+		void mock() {
+			xtaMessageMetaData = XtaMessageMetaDataTestFactory.create();
+			xdomeaMessageData = XdomeaMessageDataTestFactory.create();
+			when(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH)).thenReturn(FormHeaderTestFactory.VORGANGNUMMER);
 		}
 
 		@Test
-		void shouldHaveMessageFileAsRepresentation() {
-			var formData = mapper.toFormData(XtaMessageTestFactory.create());
+		void shouldMapRepresentations() {
+			var formData = doMapping();
 
-			assertThat(formData.getRepresentations()).hasSize(1);
+			assertThat(formData.getRepresentations()).containsExactly(xdomeaMessageData.metadataFile(), xdomeaMessageData.representations().getFirst());
 		}
 
 		@Test
-		void shouldCallToIncomingFile() {
-			XtaMessage message = XtaMessageTestFactory.create();
-
-			mapper.toFormData(message);
+		void shouldSetNumberOfAttachments() {
+			var formData = doMapping();
 
-			verify(mapper).toIncomingFile(notNull());
+			assertThat(formData.getNumberOfAttachments()).isEqualTo(1);
 		}
 
-		@Nested
-		class ToFormHeader {
-			@Test
-			void shouldMapToFormHeader() {
-				var mapped = mapper.formHeaderFromMetaData(XtaMessageMetaDataTestFactory.create());
+		@Test
+		void shouldSetNumberOfRepresentations() {
+			var formData = doMapping();
 
-				assertThat(mapped).usingRecursiveComparison().isEqualTo(FormHeaderTestFactory.create());
-			}
+			assertThat(formData.getNumberOfRepresentations()).isEqualTo(2);
 		}
 
-		@Nested
-		class ToIncomingFile {
-			@Test
-			void shouldHaveMessageFile() {
-				var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
-
-				assertThat(inFile.getContentStream()).isNotNull();
-			}
-
-			@Test
-			void shouldHaveFileName() {
-				var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
-
-				assertThat(inFile.getName()).isEqualTo(XtaFileTestFactory.NAME);
-			}
-
-			@Test
-			void shouldHaveZipContentType() {
-				var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
-
-				assertThat(inFile.getContentType()).isEqualTo("application/zip");
-			}
-
-			@Test
-			void shouldHaveSize() {
-				var inFile = mapper.toIncomingFile(XtaFileTestFactory.create());
+		@Test
+		void shouldMapAttachments() {
+			var formData = doMapping();
 
-				assertThat(inFile.getSize()).isEqualTo(XtaFileTestFactory.CONTENT.length());
-			}
+			assertThat(formData.getAttachments()).isEqualTo(xdomeaMessageData.attachments());
+		}
 
-			@Test
-			void shouldHandleMissingMessageFile() {
-				var fileGroup = mapper.toIncomingFile(null);
+		@Test
+		void shouldMapVorgangNummer() {
+			var formData = doMapping();
 
-				assertThat(fileGroup).isNull();
-			}
+			assertThat(formData.getHeader().getVorgangNummer()).isEqualTo(FormHeaderTestFactory.VORGANGNUMMER);
 		}
 
+		private FormData doMapping() {
+			return mapper.toFormData(xdomeaMessageData, xtaMessageMetaData, vorgangNummerSupplier);
+		}
 	}
 }
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java
index cb5c3f846497e9e8d9c2e39dc1fb58e4f14144da..59d354ecb7c21690e7656712e51c7c5bc56428a3 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceConfigurationTest.java
@@ -3,11 +3,13 @@ package de.ozgcloud.eingang.xta;
 import static org.assertj.core.api.Assertions.*;
 
 import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
 class XtaRemoteServiceConfigurationTest {
 
 	@Spy
+	@InjectMocks
 	XtaRemoteServiceConfiguration configuration;
 
 	@Test
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java
index dd6b6d41529a9446a78b76bdf8ccd2bf404a3cb0..a1c37d0b970039056a996ab875c6476a60abd4c5 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceTest.java
@@ -114,7 +114,7 @@ class XtaRemoteServiceTest {
 		}
 
 		@Test
-		void hosuldReturnMessageWithFile() {
+		void shouldReturnMessageWithFile() {
 			var message = service.getMessage(XtaMessageTestFactory.MESSAGE_ID);
 
 			assertThat(message.getMessageFiles()).hasSize(1).contains(file);
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceITCase.java
index 3f25039dd3c66356a1727d80ea208381fc0e03b4..cfc4776f0dd29bdd3a0b85c9236832368a863065 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceITCase.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceITCase.java
@@ -18,8 +18,6 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.ActiveProfiles;
 
 import de.ozgcloud.eingang.Application;
-import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
-import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter;
 import lombok.SneakyThrows;
 import okhttp3.mockwebserver.MockWebServer;
 
@@ -37,12 +35,6 @@ class XtaServiceITCase {
 	@Autowired
 	private XtaService xtaService;
 
-	@Autowired
-	private EngineBasedSemantikAdapter engineBasedAdapter;
-
-	@Autowired
-	private FormBasedSemantikAdapter formBasedAdapter;
-
 	@Autowired
 	private XtaProperties properties;
 
@@ -89,13 +81,16 @@ class XtaServiceITCase {
 		@Test
 		void shouldUnzipCorrectNumberOfRepresentations() {
 			var firstFormData = xtaService.getMessages().toList().getFirst();
-			assertNotNull(firstFormData);
 
-			firstFormData = engineBasedAdapter.parseFormData(firstFormData);
-			firstFormData = formBasedAdapter.parseFormData(firstFormData);
+			assertThat(firstFormData.getRepresentations()).hasSize(3);
+			assertThat(firstFormData.getNumberOfRepresentations()).isEqualTo(3);
+		}
+		@DisplayName("should unzip correct number of attachments")
+		@Test
+		void shouldUnzipCorrectNumberOfAttachments() {
+			var firstFormData = xtaService.getMessages().toList().getFirst();
 
-			// Expect that there are 3 files in attachment.zip and that the zip itself is a representation
-			assertThat(firstFormData.getNumberOfRepresentations()).isEqualTo(4);
+			assertThat(firstFormData.getAttachments()).isEmpty();
 		}
 	}
 
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 d1fc3de86803ba5fc9c49a574011b41adf8e3be0..75a00a6610db89ffeaed0ba620d4676038fda296 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
@@ -4,9 +4,9 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.List;
 import java.util.stream.Stream;
 
-import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -16,8 +16,11 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
 import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageData;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory;
+import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper;
 
 class XtaServiceTest {
 
@@ -34,12 +37,17 @@ class XtaServiceTest {
 	@Mock
 	private VorgangNummerSupplier vorgangNummerSupplier;
 
+	@Mock
+	private XtaIncomingFilesMapper incomingFilesMapper;
+
+	@Mock
+	private XdomeaMessageDataMapper xdomeaMessageDataMapper;
+
 	@Nested
 	class TestGetMessagesAsFormData {
 
-		private XtaMessageMetaDatasAndHeader metaData = XtaMessageMetaDatasAndHeaderTestFactory.create();
-		private XtaMessageMetaData messageMetaData = XtaMessageMetaDataTestFactory.create();
-		private XtaMessage message = XtaMessageTestFactory.create();
+		private final XtaMessageMetaData messageMetaData = XtaMessageMetaDataTestFactory.create();
+		private final XtaMessage message = XtaMessageTestFactory.create();
 
 		@BeforeEach
 		void setup() {
@@ -55,19 +63,17 @@ class XtaServiceTest {
 
 		@Test
 		void shouldCallFilterByMessageType() {
-			when(mapper.toFormData(any())).thenReturn(FormDataTestFactory.create());
-			when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message);
+			setupMocks();
 
 			service.getMessages().toList();
 
-			verify(service).filterByMessageType(messageMetaData);
+			verify(service).isSupportedMessageType(messageMetaData);
 		}
 
 		@Test
 		void shouldCallGetFormData() {
-			when(mapper.toFormData(any())).thenReturn(FormDataTestFactory.create());
-			when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message);
-			doReturn(true).when(service).filterByMessageType(messageMetaData);
+			setupMocks();
+			doReturn(true).when(service).isSupportedMessageType(messageMetaData);
 
 			service.getMessages().toList();
 
@@ -76,51 +82,64 @@ class XtaServiceTest {
 
 		@Test
 		void shouldNotCallGetFormData() {
-			doReturn(false).when(service).filterByMessageType(messageMetaData);
+			doReturn(false).when(service).isSupportedMessageType(messageMetaData);
 
 			service.getMessages().toList();
 
 			verify(service, never()).getFormData(any());
 		}
+
+		private void setupMocks() {
+			var testFormData = FormDataTestFactory.create();
+			when(mapper.toFormData(any(), any(), eq(vorgangNummerSupplier))).thenReturn(testFormData);
+			when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message);
+		}
 	}
 
 	@Nested
-	class TestFilterByMessageType {
+	class TestIsSupportedMessageType {
 
 		@Test
 		void shouldAcceptDFoerdermittel() {
 			var metaDataDFoerder = XtaMessageMetaDataTestFactory.create();
 
-			assertThat(service.filterByMessageType(metaDataDFoerder)).isTrue();
+			assertThat(service.isSupportedMessageType(metaDataDFoerder)).isTrue();
 		}
 
 		@Test
 		void shouldNotAcceptOtherMessageType() {
 			var metaDataDFoerder = XtaMessageMetaDataTestFactory.createBuilder().messageType(MESSAGE_TYPE_OTHER).build();
 
-			assertThat(service.filterByMessageType(metaDataDFoerder)).isFalse();
+			assertThat(service.isSupportedMessageType(metaDataDFoerder)).isFalse();
 		}
 	}
 
 	@Nested
 	class TestGetFormData {
 
-		private XtaMessage message = XtaMessageTestFactory.create();
+		private XtaMessage message;
+		private XdomeaMessageData classification;
+
+		@Captor
+		private ArgumentCaptor<XtaMessageMetaData> messageMetaDataCaptor;
 
 		@Captor
-		private ArgumentCaptor<XtaMessage> messageCaptor;
-		@Mock
-		private FormData formData;
+		private ArgumentCaptor<XdomeaMessageData>  classificationCaptor;
 
 		@BeforeEach
 		void init() {
+			message = XtaMessageTestFactory.create();
 			when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message);
+
+			classification = XdomeaMessageDataTestFactory.create();
+			var incomingFiles = List.of(IncomingFileTestFactory.create(), IncomingFileTestFactory.create());
+			when(incomingFilesMapper.toIncomingFiles(message.getMessageFiles())).thenReturn(incomingFiles);
+			classification = XdomeaMessageDataTestFactory.create();
+			when(xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles)).thenReturn(classification);
 		}
 
 		@Test
 		void shouldCallRemoteService() {
-			doReturn(formData).when(service).updateHeader(any());
-
 			service.getFormData(XtaMessageMetaDataTestFactory.create());
 
 			verify(remoteService).getMessage(XtaMessageTestFactory.MESSAGE_ID);
@@ -128,29 +147,26 @@ class XtaServiceTest {
 
 		@Test
 		void shouldCallMapper() {
-			doReturn(formData).when(service).updateHeader(any());
-
 			service.getFormData(XtaMessageMetaDataTestFactory.create());
 
-			verify(mapper).toFormData(any());
+			verify(mapper).toFormData(any(), any(), eq(vorgangNummerSupplier));
 		}
 
 		@Test
 		void shouldHaveMetaData() {
-			doReturn(formData).when(service).updateHeader(any());
 			XtaMessageMetaData metaData = XtaMessageMetaDataTestFactory.create();
 
 			service.getFormData(metaData);
 
-			verify(mapper).toFormData(messageCaptor.capture());
-			assertThat(messageCaptor.getValue().getMetaData()).isNotNull().isEqualTo(metaData);
+			verify(mapper).toFormData(classificationCaptor.capture(), messageMetaDataCaptor.capture(), eq(vorgangNummerSupplier));
+			assertThat(messageMetaDataCaptor.getValue()).isEqualTo(metaData);
+			assertThat(classificationCaptor.getValue()).isEqualTo(classification);
 		}
 
 		@Test
 		void shouldReturnMappedResult() {
 			var mapped = FormDataTestFactory.create();
-			when(mapper.toFormData(any())).thenReturn(mapped);
-			doReturn(mapped).when(service).updateHeader(any());
+			when(mapper.toFormData(any(), any(), eq(vorgangNummerSupplier))).thenReturn(mapped);
 
 			var result = service.getFormData(XtaMessageMetaDataTestFactory.create());
 
@@ -158,50 +174,6 @@ class XtaServiceTest {
 		}
 	}
 
-	@Nested
-	class TestUpdateHeader {
-
-		@Test
-		void shouldCallSetVorgangNummer() {
-			var formData = FormDataTestFactory.create();
-
-			service.updateHeader(formData);
-
-			verify(service).setVorgangNummer(formData.getHeader());
-		}
-
-		@Test
-		void shouldSetUpdatedHeader() {
-			var updatedHeader = FormHeaderTestFactory.create();
-			doReturn(updatedHeader).when(service).setVorgangNummer(any());
-
-			var result = service.updateHeader(FormDataTestFactory.create());
-
-			Assertions.assertThat(result.getHeader()).isSameAs(updatedHeader);
-		}
-	}
-
-	@Nested
-	class TestSetVorgangNummer {
-
-		@Test
-		void shouldCallVorgangNummerSupplier() {
-			service.setVorgangNummer(FormHeaderTestFactory.create());
-
-			verify(vorgangNummerSupplier).get(XtaService.VORGANG_NUMMER_SUFFIX_LENGTH);
-		}
-
-		@Test
-		void shouldSetVorgangNummer() {
-			var vorgangNummer = "vorgang-1";
-			when(vorgangNummerSupplier.get(anyInt())).thenReturn(vorgangNummer);
-
-			var result = service.setVorgangNummer(FormHeaderTestFactory.create());
-
-			assertThat(result.getVorgangNummer()).isEqualTo(vorgangNummer);
-		}
-	}
-
 	@Nested
 	class TestAcknowledgeReceive {
 
diff --git a/xta-adapter/src/test/resources/test_content.zip b/xta-adapter/src/test/resources/test_content.zip
deleted file mode 100644
index e2c9e434c49cf52a8d0840b1a25dcc52615df04c..0000000000000000000000000000000000000000
Binary files a/xta-adapter/src/test/resources/test_content.zip and /dev/null differ
diff --git a/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28200a104f3cb7ded5851105ad2d9fd80034bc3c
--- /dev/null
+++ b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Geschaeftsgang.Geschaeftsgang.0201 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="urn:xoev-de:xdomea:schema:2.4.0 xdomea-Nachrichten-VBS.xsd" xmlns="urn:xoev-de:xdomea:schema:2.4.0">
+  <Kopf>
+    <ProzessID>b42b7984-279c-4260-8b48-c0389555608c</ProzessID>
+    <Nachrichtentyp listURI="urn:xoev-de:xdomea:codeliste:nachrichtentyp" listVersionID="1.0">
+      <code xmlns="">0201</code>
+    </Nachrichtentyp>
+    <Erstellungszeitpunkt>2024-04-22T16:14:18.1885313+02:00</Erstellungszeitpunkt>
+    <Absender>
+      <Behoerdenkennung>
+        <Kennung listURI="" listVersionID="">
+          <code xmlns="">010200200000</code>
+        </Kennung>
+        <Praefix listURI="" listVersionID="">
+          <code xmlns="">gad</code>
+        </Praefix>
+      </Behoerdenkennung>
+    </Absender>
+    <Empfaenger>
+      <Behoerdenkennung>
+        <Kennung listURI="" listVersionID="">
+          <code xmlns="">dev-environment@ozg-cloud.de</code>
+        </Kennung>
+        <Praefix listURI="" listVersionID="">
+          <code xmlns="">gae</code>
+        </Praefix>
+      </Behoerdenkennung>
+    </Empfaenger>
+    <SendendesSystem>
+      <InstanzID>HH_dFoerdermittelantrag</InstanzID>
+      <Produktname>dFoerdermittelantrag</Produktname>
+      <Version>2.1.999.0</Version>
+    </SendendesSystem>
+    <EmpfangsbestaetigungAnInitiator>false</EmpfangsbestaetigungAnInitiator>
+    <EmpfangsbestaetigungAnVorgaenger>false</EmpfangsbestaetigungAnVorgaenger>
+  </Kopf>
+  <Hauptobjekt>
+    <Dokument>
+      <Identifikation>
+        <ID>0e7734d8-bf3f-4f8d-9568-3791abf8fe44</ID>
+      </Identifikation>
+      <AllgemeineMetadaten>
+        <Betreff>Testantrag für die OZG-Cloud</Betreff>
+        <Kennzeichen>08dc497a-f1d4-412d-80ca-4f58405dc83e</Kennzeichen>
+      </AllgemeineMetadaten>
+      <Version>
+        <Nummer>1</Nummer>
+        <Format>
+          <Name listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" xsi:type="DateiformatCodeType">
+            <code xmlns="">030</code>
+            <name xmlns="">xml-eXtensible Markup Language</name>
+          </Name>
+          <Version>0.0</Version>
+          <Primaerdokument>
+            <Dateiname>%s</Dateiname>
+          </Primaerdokument>
+        </Format>
+        <Format>
+          <Name listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" xsi:type="DateiformatCodeType">
+            <code xmlns="">018</code>
+            <name xmlns="">pdf-Portable Document Format</name>
+          </Name>
+          <Version>0.0</Version>
+          <Primaerdokument>
+            <Dateiname>%s</Dateiname>
+          </Primaerdokument>
+        </Format>
+      </Version>
+    </Dokument>
+  </Hauptobjekt>
+  <ExternerGeschaeftsgang>
+    <Identifikation>
+      <ID>78fd7cf4-e9b2-4df1-9dc3-3b192a9d61d3</ID>
+    </Identifikation>
+    <Beteiligungsschritt>
+      <Nummer>1</Nummer>
+      <Status listURI="urn:xoev-de:xdomea:codeliste:beteiligungsstatus" listVersionID="1.0">
+        <code xmlns="">001</code>
+        <name xmlns="">Der Schritt liegt in der Zukunft.</name>
+      </Status>
+      <Verfuegung>
+        <Ersteller>
+          <Behoerdenkennung>
+            <Kennung listURI="" listVersionID="">
+              <code xmlns="">010200200000</code>
+            </Kennung>
+            <Praefix listURI="" listVersionID="">
+              <code xmlns="">gad</code>
+            </Praefix>
+          </Behoerdenkennung>
+        </Ersteller>
+        <Adressat>
+          <Behoerdenkennung>
+            <Kennung listURI="" listVersionID="">
+              <code xmlns="">dev-environment@ozg-cloud.de</code>
+            </Kennung>
+            <Praefix listURI="" listVersionID="">
+              <code xmlns="">gae</code>
+            </Praefix>
+          </Behoerdenkennung>
+        </Adressat>
+        <Erstellungsdatum>2024-04-22</Erstellungsdatum>
+        <Erstellungsuhrzeit>16:14:18</Erstellungsuhrzeit>
+      </Verfuegung>
+    </Beteiligungsschritt>
+  </ExternerGeschaeftsgang>
+</Geschaeftsgang.Geschaeftsgang.0201>
diff --git a/xta-adapter/src/test/resources/xdomea/dfoerdermittel_without_anlage.zip b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_without_anlage.zip
new file mode 100644
index 0000000000000000000000000000000000000000..a05e0656982591208af644af4478ad6c6fe58f10
Binary files /dev/null and b/xta-adapter/src/test/resources/xdomea/dfoerdermittel_without_anlage.zip differ
diff --git a/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2897dbe4fd05a17463edbe13d37824ae64d99b59
--- /dev/null
+++ b/xta-adapter/src/test/resources/xdomea/mantelantrag_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1">
+	<xdomea:Kopf>
+		<xdomea:ProzessID>9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2</xdomea:ProzessID>
+		<xdomea:Nachrichtentyp codeName="Geschaeftsgang.Geschaeftsgang.0201" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Nachrichtentyp">0201</xdomea:Nachrichtentyp>
+		<xdomea:Erstellungszeitpunkt>2024-04-04T10:24:07.468+02:00</xdomea:Erstellungszeitpunkt>
+		<xdomea:Absender>
+			<xdomea:Behoerdenkennung>
+				<xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung>
+				<xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix>
+			</xdomea:Behoerdenkennung>
+			<xdomea:Institution>
+				<xdomea:Name>Schleswig-Holstein</xdomea:Name>
+				<xdomea:Kurzbezeichnung>Schleswig-Holstein</xdomea:Kurzbezeichnung>
+			</xdomea:Institution>
+		</xdomea:Absender>
+		<xdomea:Empfaenger>
+			<xdomea:Behoerdenkennung>
+				<xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung>
+				<xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix>
+			</xdomea:Behoerdenkennung>
+		</xdomea:Empfaenger>
+		<xdomea:SendendesSystem>
+			<xdomea:InstanzID>AFMSH.MSR</xdomea:InstanzID>
+			<xdomea:Produktname>MSR</xdomea:Produktname>
+			<xdomea:Version>10.5</xdomea:Version>
+		</xdomea:SendendesSystem>
+		<xdomea:EmpfangsbestaetigungAnInitiator>false</xdomea:EmpfangsbestaetigungAnInitiator>
+		<xdomea:EmpfangsbestaetigungAnVorgaenger>false</xdomea:EmpfangsbestaetigungAnVorgaenger>
+	</xdomea:Kopf>
+	<xdomea:Hauptobjekt>
+		<xdomea:Dokument>
+			<xdomea:Identifikation>
+				<xdomea:ID>9bae73b1-2ef3-480b-8acc-8bcd9979a788</xdomea:ID>
+			</xdomea:Identifikation>
+			<xdomea:AllgemeineMetadaten>
+				<xdomea:Betreff>Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe</xdomea:Betreff>
+				<xdomea:Kennzeichen>20240404370530710707</xdomea:Kennzeichen>
+			</xdomea:AllgemeineMetadaten>
+			<xdomea:Posteingangsdatum>2024-04-04</xdomea:Posteingangsdatum>
+			<xdomea:Typ>maa_mantelantrag/maa_mantelantrag_pvog</xdomea:Typ>
+			<xdomea:Version>
+				<xdomea:Nummer>0.0</xdomea:Nummer>
+				<xdomea:Format>
+					<xdomea:Name codeName="xml - eXtensible Markup Language" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Dateiformat">030</xdomea:Name>
+					<xdomea:Version>0.0</xdomea:Version>
+					<xdomea:Primaerdokument>
+						<xdomea:Dateiname>%s</xdomea:Dateiname>
+					</xdomea:Primaerdokument>
+				</xdomea:Format>
+			</xdomea:Version>
+			<xdomea:Version>
+				<xdomea:Nummer>0.0</xdomea:Nummer>
+				<xdomea:Format>
+					<xdomea:Name codeName="pdf - Portable Document Format" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Dateiformat">018</xdomea:Name>
+					<xdomea:Version>0.0</xdomea:Version>
+					<xdomea:Primaerdokument>
+						<xdomea:Dateiname>%s</xdomea:Dateiname>
+					</xdomea:Primaerdokument>
+				</xdomea:Format>
+			</xdomea:Version>
+		</xdomea:Dokument>
+	</xdomea:Hauptobjekt>
+	<xdomea:ExternerGeschaeftsgang>
+		<xdomea:Identifikation>
+			<xdomea:ID>8ae49342-8135-4f11-9930-5c4cc55b7ec2</xdomea:ID>
+		</xdomea:Identifikation>
+		<xdomea:Beteiligungsschritt>
+			<xdomea:Nummer>1</xdomea:Nummer>
+			<xdomea:Status codeName="zukuenftig" codelistAgencyName="AG XDOMEA des KoopA ADV" codelistVersionIdentifier="2.0.0" languageCode="de" codelistName="Beteiligungsstatus">001</xdomea:Status>
+			<xdomea:Verfuegung>
+				<xdomea:Ersteller>
+					<xdomea:Behoerdenkennung>
+						<xdomea:Kennung codeName="WebMethod_Online-Dienste">WebMethod_Online-Dienste</xdomea:Kennung>
+						<xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix>
+					</xdomea:Behoerdenkennung>
+				</xdomea:Ersteller>
+				<xdomea:Adressat>
+					<xdomea:Behoerdenkennung>
+						<xdomea:Kennung codeName="ozg-cloud-dev001">ozg-cloud-dev001</xdomea:Kennung>
+						<xdomea:Praefix codeName="afmsh:">afmsh:</xdomea:Praefix>
+					</xdomea:Behoerdenkennung>
+				</xdomea:Adressat>
+				<xdomea:Erstellungsdatum>2024-04-04</xdomea:Erstellungsdatum>
+				<xdomea:Erstellungsuhrzeit>10:24:06</xdomea:Erstellungsuhrzeit>
+			</xdomea:Verfuegung>
+		</xdomea:Beteiligungsschritt>
+	</xdomea:ExternerGeschaeftsgang>
+</xdomea:Geschaeftsgang.Geschaeftsgang.0201>