diff --git a/common/pom.xml b/common/pom.xml
index 30d5659794f107e25c422b89d060f869695e6264..df50f9ca133319c015c1c39e9d8718c64d6d8f07 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -31,7 +31,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 		<relativePath>../</relativePath>
 	</parent>
 	<artifactId>common</artifactId>
diff --git a/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java b/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java
index ab2f7588d424a1358a4d8bcd01d360e705917e86..6cce21a27b16bcf67062209a83427366ba35b583 100644
--- a/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java
+++ b/common/src/main/java/de/ozgcloud/eingang/common/formdata/ServiceKonto.java
@@ -1,9 +1,14 @@
 package de.ozgcloud.eingang.common.formdata;
 
+import java.util.EnumSet;
 import java.util.List;
 
+import org.apache.commons.lang3.StringUtils;
+
+import lombok.AccessLevel;
 import lombok.Builder;
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
 import lombok.Singular;
 
 @Getter
@@ -22,4 +27,23 @@ public class ServiceKonto {
 		private String version;
 		private PostfachAddressIdentifier identifier;
 	}
+
+	@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+	public enum TrustLevel {
+
+		LEVEL_1("STORK-QAA-Level-1"),
+		LEVEL_2("STORK-QAA-Level-2"),
+		LEVEL_3("STORK-QAA-Level-3"),
+		LEVEL_4("STORK-QAA-Level-4");
+
+		private final String value;
+
+		public static boolean exists(String trustLevelValue) {
+			if (StringUtils.isBlank(trustLevelValue)) {
+				return false;
+			}
+			return EnumSet.allOf(TrustLevel.class).stream().map(trustLevel -> trustLevel.value).anyMatch(trustLevelValue::equalsIgnoreCase);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/TrustLevelTest.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/TrustLevelTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..93c12966a7e2b57ae3053bb583e585d6683025d9
--- /dev/null
+++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/TrustLevelTest.java
@@ -0,0 +1,32 @@
+package de.ozgcloud.eingang.common.formdata;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import de.ozgcloud.eingang.common.formdata.ServiceKonto.TrustLevel;
+
+class TrustLevelTest {
+
+	@DisplayName("should return true when")
+	@ParameterizedTest(name = "trust level is {0}")
+	@ValueSource(strings = {"STORK-QAA-Level-1", "STORK-QAA-Level-2", "STORK-QAA-Level-3", "STORK-QAA-Level-4"})
+	void shouldReturnTrue(String trustLevel) {
+		var isValid = TrustLevel.exists(trustLevel);
+
+		assertThat(isValid).isTrue();
+	}
+
+	@DisplayName("should return false when")
+	@ParameterizedTest(name = "trust level is \"{0}\"")
+	@NullAndEmptySource
+	@ValueSource(strings = {"STORK-QAA-Level-0", "unexpected"})
+	void shouldReturnFalse(String trustLevel) {
+		var isValid = TrustLevel.exists(trustLevel);
+
+		assertThat(isValid).isFalse();
+	}
+}
\ No newline at end of file
diff --git a/enterprise-adapter/pom.xml b/enterprise-adapter/pom.xml
index 9db735be38bbccf7790d13fb2024f18751a68743..c3d6d8991bb79eeeeebee78a6b41a335010ea1fd 100644
--- a/enterprise-adapter/pom.xml
+++ b/enterprise-adapter/pom.xml
@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 	</parent>
 	<artifactId>enterprise-adapter</artifactId>
 	<name>EM - Enterprise Interface Adapter</name>
diff --git a/formcycle-adapter/formcycle-adapter-impl/pom.xml b/formcycle-adapter/formcycle-adapter-impl/pom.xml
index 6a0ee94001fcb3949a0da8d2348b89a2204011d9..22b2544e84028f4529ef5dba518143371da2b628 100644
--- a/formcycle-adapter/formcycle-adapter-impl/pom.xml
+++ b/formcycle-adapter/formcycle-adapter-impl/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>formcycle-adapter</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 		<relativePath>../</relativePath>
 	</parent>
 
diff --git a/formcycle-adapter/formcycle-adapter-interface/pom.xml b/formcycle-adapter/formcycle-adapter-interface/pom.xml
index f4b4df771e63084db8be2911e8d470d5b9e2fbc4..934fda4a294112802a3b6eee1dec7237af988dc1 100644
--- a/formcycle-adapter/formcycle-adapter-interface/pom.xml
+++ b/formcycle-adapter/formcycle-adapter-interface/pom.xml
@@ -29,14 +29,14 @@
 	<parent>
 		<groupId>de.ozgcloud.common</groupId>
 		<artifactId>ozgcloud-common-dependencies</artifactId>
-		<version>4.0.1</version>
+		<version>4.2.0</version>
 		<relativePath/>
 	</parent>
 
 	<groupId>de.ozgcloud.eingang</groupId>
 	<artifactId>formcycle-adapter-interface</artifactId>
 	<name>EM - Formcycle Adapter - Interface</name>
-	<version>2.7.0-SNAPSHOT</version>
+	<version>2.9.0-SNAPSHOT</version>
 	
 	<properties>
 		<vorgang-manager.version>2.0.0</vorgang-manager.version>
diff --git a/formcycle-adapter/pom.xml b/formcycle-adapter/pom.xml
index 744c618971f7acbb70f27b600b038c66aa6727b9..f8d8a7d4336b441deac1064a0de762afc611bb3b 100644
--- a/formcycle-adapter/pom.xml
+++ b/formcycle-adapter/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>formcycle-adapter</artifactId>
diff --git a/formsolutions-adapter/pom.xml b/formsolutions-adapter/pom.xml
index 3333c42c1c469c176d199960deb18a51d12e4785..6b4173a3e100d3242c3ef243ab565e43ae98ad3a 100644
--- a/formsolutions-adapter/pom.xml
+++ b/formsolutions-adapter/pom.xml
@@ -30,7 +30,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 		<relativePath>../</relativePath>
 	</parent>
 
diff --git a/forwarder/pom.xml b/forwarder/pom.xml
index b0841bad595825b8bc8817bdf7742e7fee789dfd..f02fa4fc7f94b51fe32babced7ac30608442fec1 100644
--- a/forwarder/pom.xml
+++ b/forwarder/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 		<relativePath>../</relativePath>
 	</parent>
 
diff --git a/intelliform-adapter/pom.xml b/intelliform-adapter/pom.xml
index 75a304118ad028eb716199dcf9f5dde9ce11ba19..68fc3653ecd982cb5380f665d506b9464df06896 100644
--- a/intelliform-adapter/pom.xml
+++ b/intelliform-adapter/pom.xml
@@ -31,7 +31,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 		<relativePath>../</relativePath>
 	</parent>
 
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/DepositDataMapper.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..b12dfc7a99548a5868891da6608dab10242e64d2
--- /dev/null
+++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/DepositDataMapper.java
@@ -0,0 +1,181 @@
+/*
+ * 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 java.util.stream.Collectors.*;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+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 javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+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 lombok.RequiredArgsConstructor;
+
+@Component
+@RequiredArgsConstructor
+class DepositDataMapper {
+
+	// TODO Resolve code duplication (xta-adapter: de.ozgcloud.eingang.xdomea.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);
+		}
+	}
+
+	public FormData mapToFormData(DepositData depositData) {
+		Map<String, IncomingFile> incomingFileMap = mapDepositAttachmentsToIncomingFiles(depositData);
+		Document document = parsePrimaryXmlRepresentation(depositData, incomingFileMap);
+		var attachmentGroups = findAttachmentGroups(document);
+
+		return mapToFormDataWithRepresentationsAndAttachments(
+				getRepresentations(incomingFileMap, getAttachmentFileIds(attachmentGroups)),
+				getAttachmentFileGroups(attachmentGroups, incomingFileMap)
+		);
+	}
+
+	private List<String> getAttachmentFileIds(Map<String, List<String>> attachmentGroups) {
+		return attachmentGroups.values().stream()
+				.flatMap(Collection::stream)
+				.toList();
+	}
+
+	private FormData mapToFormDataWithRepresentationsAndAttachments(
+			List<IncomingFile> representations,
+			List<IncomingFileGroup> attachments
+	) {
+		return FormData.builder()
+				.attachments(attachments)
+				.numberOfAttachments(attachments.size())
+				.representations(representations)
+				.numberOfRepresentations(representations.size())
+				.build();
+	}
+
+	Map<String, IncomingFile> mapDepositAttachmentsToIncomingFiles(DepositData depositData) {
+		return depositData.getAttachments()
+				.stream()
+				.collect(Collectors.toMap(
+						Attachment::getId,
+						this::mapAttachmentToIncomingFile,
+						(u, v) -> v,
+						LinkedHashMap::new));
+	}
+
+	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();
+	}
+
+	private Document parsePrimaryXmlRepresentation(DepositData depositData, Map<String, IncomingFile> incomingFileMap) {
+		// Expect that the <primaryDataAttachmentId> refers to the XML file
+		return parseDocument(
+				getIncomingFileById(depositData.getPrimaryDataAttachmentId(), incomingFileMap)
+		);
+	}
+
+	private 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);
+		}
+	}
+
+	Map<String, List<String>> findAttachmentGroups(Document document) {
+		return streamElements(document.getElementsByTagName("file"))
+				.collect(groupingBy(
+						element -> element.getParentNode().getNodeName(),
+						mapping(
+								element -> element.getAttribute("id"),
+								toList())));
+	}
+
+	private List<IncomingFileGroup> getAttachmentFileGroups(Map<String, List<String>> attachmentGroups, Map<String, IncomingFile> incomingFileMap) {
+		return attachmentGroups.entrySet().stream()
+				.map(entry -> IncomingFileGroup.builder()
+						.name(entry.getKey())
+						.files(entry.getValue().stream().map(id -> getIncomingFileById(id, incomingFileMap)).toList())
+						.build())
+				.toList();
+	}
+
+	private List<IncomingFile> getRepresentations(Map<String, IncomingFile> incomingFileMap, List<String> attachmentFileIds) {
+		return getNamesWithout(incomingFileMap.keySet(), attachmentFileIds).stream()
+				.map(id -> getIncomingFileById(id, incomingFileMap))
+				.toList();
+	}
+
+	private IncomingFile getIncomingFileById(String id, Map<String, IncomingFile> incomingFileMap) {
+		if (!incomingFileMap.containsKey(id)) {
+			throw new TechnicalException("Failed to find <file> attachment ID '%s' in deposit data!".formatted(id));
+		}
+		return incomingFileMap.get(id);
+	}
+
+	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 Stream<Element> streamElements(NodeList nodeList) {
+		return IntStream.range(0, nodeList.getLength())
+				.mapToObj(nodeList::item)
+				.map(Element.class::cast);
+	}
+
+}
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/FormDataEndpoint.java b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java
index dbacf18bbedcc706eddaad92c197a1e6e7be9c8f..f9caf285a578e2f88316386481331476e6392093 100644
--- a/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java
+++ b/intelliform-adapter/src/main/java/de/ozgcloud/eingang/intelliform/FormDataEndpoint.java
@@ -50,8 +50,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 DepositDataMapper depositDataMapper;
 	@Autowired
 	private SemantikAdapter semantikAdapter;
 
@@ -60,7 +61,8 @@ public class FormDataEndpoint {
 	public JAXBElement<DepositResponse> inputFormData(@RequestPayload Deposit deposit)
 			throws IOException, ParserConfigurationException {
 		try {
-			semantikAdapter.processFormData(semantikFormDataMapper.mapToFormData(deposit));
+			var formData = depositDataMapper.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/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/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/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..38a0efcc22bbc6b409fbd7f1122ef74fb00de136
--- /dev/null
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/DepositDataMapperTest.java
@@ -0,0 +1,309 @@
+/*
+ * 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.io.IOException;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+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 org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import lombok.SneakyThrows;
+
+class DepositDataMapperTest {
+
+	@Spy
+	private DepositDataMapper 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).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID);
+			}
+
+			@DisplayName("should return with one attachment")
+			@Test
+			void shouldReturnWithOneAttachment() {
+				var formData = doMapping();
+
+				var incomingFileIds = formData.getAttachments().stream()
+						.flatMap(group -> group.getFiles().stream())
+						.map(IncomingFile::getVendorId)
+						.toList();
+				assertThat(incomingFileIds).containsExactly(PNG_ATTACHMENT_ID);
+			}
+
+			@DisplayName("should return with attachment group name")
+			@Test
+			void shouldReturnWithAttachmentGroupName() {
+				var formData = doMapping();
+
+				var incomingFileIds = formData.getAttachments().stream()
+						.map(IncomingFileGroup::getName)
+						.toList();
+				assertThat(incomingFileIds).containsExactly("Upload1");
+			}
+
+			@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);
+		}
+
+	}
+
+	@DisplayName("map deposit attachments to incoming files")
+	@Nested
+	class TestMapDepositAttachmentsToIncomingFiles {
+		@DisplayName("should keep entry order")
+		@Test
+		void shouldKeepEntryOrder() {
+			var depositData = DepositDataTestFactory.create(ATTACHMENTS);
+
+			var incomingFileMap = mapper.mapDepositAttachmentsToIncomingFiles(depositData);
+
+			var keys = incomingFileMap.keySet().stream().toList();
+			assertThat(keys).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID, PNG_ATTACHMENT_ID);
+		}
+
+		@DisplayName("should keep last entry for duplicate key")
+		@Test
+		void shouldKeepLastEntryForDuplicateKey() {
+			var depositData = DepositDataTestFactory.create(List.of(
+					AttachmentTestFactory.createXmlDaten(),
+					AttachmentTestFactory.createPdf(),
+					AttachmentTestFactory.createXmlDaten()
+			));
+
+			var incomingFileMap = mapper.mapDepositAttachmentsToIncomingFiles(depositData);
+
+			var keys = incomingFileMap.keySet().stream().toList();
+			assertThat(keys).containsExactly(XML_ATTACHMENT_ID, PDF_ATTACHMENT_ID);
+		}
+	}
+
+	@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);
+		}
+	}
+
+	@DisplayName("find attachment groups")
+	@Nested
+	class TestFindAttachmentGroups {
+
+		private Document document;
+
+		@BeforeEach
+		void mock() {
+			document = buildXMLDocument("""
+					<myForm t:client-id="land">
+					  <Upload1>
+					    <file content-type="image/png" description="" id="VendorId3333" length="155251">Image.png</file>
+					  </Upload1>
+					  <Upload2>
+					    <file id="VendorId1111">name1.txt</file>
+					    <file id="VendorId2222">name2.txt</file>
+					  </Upload2>
+					  <file id="VendorIdxxxx">namex.txt</file>
+					</myForm>""");
+		}
+
+		@DisplayName("should have groups with parent element name")
+		@Test
+		void shouldHaveGroupsWithParentElementName() {
+			var attachmentGroups = mapper.findAttachmentGroups(document);
+
+			assertThat(attachmentGroups).containsOnlyKeys("Upload1", "Upload2", "myForm");
+		}
+
+		@DisplayName("should have Upload1 group with fileId")
+		@Test
+		void shouldHaveUpload1GroupWithFileId() {
+			var attachmentGroups = mapper.findAttachmentGroups(document);
+
+			assertThat(attachmentGroups.get("Upload1")).containsExactly("VendorId3333");
+		}
+
+		@DisplayName("should have two fileIds in Upload2 group")
+		@Test
+		void shouldHaveTwoFileIdsInUpload2Group() {
+			var attachmentGroups = mapper.findAttachmentGroups(document);
+
+			assertThat(attachmentGroups.get("Upload2")).containsExactly("VendorId1111", "VendorId2222");
+		}
+	}
+
+	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/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/FormDataEndpointTest.java b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java
index c6c9381d3ca42453ede63033b277c7e1d00261ef..b58584e84b0ccf8362a448a506449d67bc7a23c2 100644
--- a/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java
+++ b/intelliform-adapter/src/test/java/de/ozgcloud/eingang/intelliform/FormDataEndpointTest.java
@@ -45,20 +45,20 @@ import de.ozgcloud.eingang.semantik.SemantikAdapter;
 class FormDataEndpointTest {
 
 	@InjectMocks
-	private FormDataEndpoint formdataEndpoint;
+	private FormDataEndpoint formdataEndpointIntelli;
 	@Mock
-	private SemantikFormDataMapper semantikFormDataMapper;
+	private DepositDataMapper depositDataMapper;
 	@Mock
 	private SemantikAdapter semantikAdapter;
 
 	@BeforeEach
 	void init() throws SAXException, IOException, ParserConfigurationException {
-		when(semantikFormDataMapper.mapToFormData(any())).thenReturn(FormDataTestFactory.create());
+		when(depositDataMapper.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/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/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/pom.xml b/pom.xml
index 842a106415d04ecc600bdefb8a236e9b447aa6ca..c10707fec21d9abe0d655a98ae5584c61a1e553f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,13 +31,13 @@
 	<parent>
 		<groupId>de.ozgcloud.common</groupId>
 		<artifactId>ozgcloud-common-parent</artifactId>
-		<version>4.0.1</version>
+		<version>4.2.0</version>
 		<relativePath/> <!-- lookup parent from repository -->
 	</parent>
 
 	<groupId>de.ozgcloud.eingang</groupId>
 	<artifactId>eingang-manager</artifactId>
-	<version>2.7.0-SNAPSHOT</version>
+	<version>2.9.0-SNAPSHOT</version>
 	<packaging>pom</packaging>
 	<name>OZG-Cloud Eingang Manager</name>
 
@@ -54,7 +54,7 @@
 	</modules>
 
 	<properties>
-		<vorgang-manager.version>2.7.0-SNAPSHOT</vorgang-manager.version>
+		<vorgang-manager.version>2.7.0</vorgang-manager.version>
 
 		<jsoup.version>1.14.3</jsoup.version>
 		<xmlschema.version>2.3.0</xmlschema.version>
diff --git a/router/pom.xml b/router/pom.xml
index 3f53f90aab040b701dc55217cd2bf7165eed88d5..2ef9bc41b72e98f8293475662c8c4bbf142b4c25 100644
--- a/router/pom.xml
+++ b/router/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 		<relativePath>../</relativePath>
 	</parent>
 
diff --git a/run_helm_test.sh b/run_helm_test.sh
index b19a9bc7c3072044dff8f0fb54c04c29acc3fbf6..ccc03d0fb89a1d2eb4c637c7d5f68ffd283051e7 100755
--- a/run_helm_test.sh
+++ b/run_helm_test.sh
@@ -4,4 +4,4 @@ set -e
 
 helm template  ./src/main/helm/ -f src/test/helm-linter-values.yaml
 helm lint -f src/test/helm-linter-values.yaml ./src/main/helm/
-cd src/main/helm && helm unittest  -f '../../test/helm/**/*test.yaml' .
\ No newline at end of file
+cd src/main/helm && helm unittest  -f '../../test/helm/**/*.yaml' .
\ No newline at end of file
diff --git a/semantik-adapter/pom.xml b/semantik-adapter/pom.xml
index d80a72d50482be10bf3ed8c1541c1829151d7a73..db797d49719877d7d294b248f6f3b90ea84a6dd3 100644
--- a/semantik-adapter/pom.xml
+++ b/semantik-adapter/pom.xml
@@ -30,7 +30,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 	</parent>
 	
 	<artifactId>semantik-adapter</artifactId>
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..47a3d8570d4b2b6c3b3b7aaa5a5d2bba58271f57 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,7 @@
  */
 package de.ozgcloud.eingang.semantik;
 
-import java.util.Objects;
+import java.util.List;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -36,11 +36,10 @@ import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter;
 @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 +51,19 @@ public class SemantikAdapter {
 	}
 
 	private FormData parseByEngineAdapter(FormData formData) {
-		if (Objects.nonNull(engineBasedAdapter)) {
-			return engineBasedAdapter.parseFormData(formData);
+		for (var adapter : getResponsibleEngineAdapters(formData)) {
+			formData = adapter.parseFormData(formData);
 		}
 		return formData;
 	}
 
+	List<EngineBasedSemantikAdapter> getResponsibleEngineAdapters(FormData formData) {
+		return engineBasedAdapters.stream()
+				.filter(adapter -> adapter.isResponsible(formData))
+				.toList();
+	}
+
 	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/ServiceKontoBuildHelper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactory.java
similarity index 71%
rename from semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelper.java
rename to semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactory.java
index 1ec87a0e456865b00b7edbddf0834dad0f8e9948..0b7320fbe23a0a9820ccebfa9c82fd78347798f4 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.semantik.enginebased;
+package de.ozgcloud.eingang.semantik.common;
 
 import java.util.Collections;
 import java.util.List;
@@ -6,21 +6,27 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
+import org.apache.commons.collections.MapUtils;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.PostfachAddressIdentifier;
 import de.ozgcloud.eingang.common.formdata.ServiceKonto;
-import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
 import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress;
+import de.ozgcloud.eingang.common.formdata.ServiceKonto.TrustLevel;
+import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
+import lombok.extern.log4j.Log4j2;
 
 @Component
-public class ServiceKontoBuildHelper {
+@Log4j2
+public class ServiceKontoFactory {
 
 	public static final int POSTFACH_ADDRESS_DEFAULT = 1;
 	public static final String POSTFACH_TYPE_OSI = "OSI";
 	public static final String POSTFACH_TYPE_BAYERN_ID = "BayernID";
 	public static final String POSTFACH_VERSION = "1.0";
+	public static final String KEY_BAYERN_ID_POSTFACH_ID = "u:saml_legacypostkorbhandle";
+	public static final String KEY_BAYERN_ID_TRUST_LEVEL = "u:saml_eid_citizen_qaa_level";
 
 	public static final String REST_RESPONSE_NAME = "rest_response_name";
 	public static final String REST_RESPONSE_NAME_MEMBER_SCOPE = "memberscope";
@@ -85,8 +91,27 @@ public class ServiceKontoBuildHelper {
 		return ((List<Map<String, Object>>) restResponseName.get(REST_RESPONSE_NAME_MEMBER_SCOPE)).get(0);
 	}
 
-	public ServiceKonto buildBayernIdServiceKonto(String postfachId) {
-		return ServiceKonto.builder().type(POSTFACH_TYPE_BAYERN_ID).postfachAddress(buildPostfachAddress(postfachId)).build();
+	public Optional<ServiceKonto> createBayernIdServiceKonto(Map<String, Object> formDataHeaders) {
+		if (Objects.isNull(formDataHeaders) || !formDataHeaders.containsKey(KEY_BAYERN_ID_POSTFACH_ID)) {
+			return Optional.empty();
+		}
+		if (isValidTrustLevel(formDataHeaders)) {
+			return Optional.of(buildBayernIdServiceKonto(formDataHeaders));
+		}
+		LOG.error("TrustLevel has an unexpected value '{}'. BayernID user account is not connected", getTrustLevel(formDataHeaders));
+		return Optional.empty();
+	}
+
+	boolean isValidTrustLevel(Map<String, Object> formDataHeader) {
+		return TrustLevel.exists(getTrustLevel(formDataHeader));
+	}
+
+	ServiceKonto buildBayernIdServiceKonto(Map<String, Object> formDataHeaders) {
+		return ServiceKonto.builder()
+				.type(POSTFACH_TYPE_BAYERN_ID)
+				.postfachAddress(buildPostfachAddress(MapUtils.getString(formDataHeaders, KEY_BAYERN_ID_POSTFACH_ID)))
+				.trustLevel(getTrustLevel(formDataHeaders))
+				.build();
 	}
 
 	PostfachAddress buildPostfachAddress(String postkorbHandle) {
@@ -101,4 +126,8 @@ public class ServiceKontoBuildHelper {
 		return StringBasedIdentifier.builder().postfachId(postfachId).build();
 	}
 
+	String getTrustLevel(Map<String, Object> formDataHeaders) {
+		return MapUtils.getString(formDataHeaders, KEY_BAYERN_ID_TRUST_LEVEL);
+	}
+
 }
\ 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..9679dc725335d8c95f9e7e1114c7c0a5d48f22ce 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);
+
+	// TODO Umbauen zu `public String[] getFormEngines();`
+	default boolean isResponsible(FormData formData) {
+		return true;
+	}
 }
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java
index 3171846b129f4f676a7392d2f857e0f72714705c..df134be93dbf148d8cc9f2009d9f2ad6ec6d581d 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapper.java
@@ -6,16 +6,17 @@ import static org.apache.commons.lang3.StringUtils.*;
 import java.util.Collections;
 import java.util.Map;
 
+import org.apache.commons.collections.MapUtils;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
 import de.ozgcloud.eingang.common.formdata.Antragsteller;
 import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 @Component
 public class AfmAntragstellerHeaderMapper {
 
-	static final String KEY_POSTFACH_ID = "u:saml_legacypostkorbhandle";
 	static final String KEY_VORNAME = "u:saml_givenname";
 	static final String KEY_NACHNAME = "u:saml_surname";
 	static final String KEY_GEBURTSORT = "u:saml_placeofbirth";
@@ -32,22 +33,23 @@ public class AfmAntragstellerHeaderMapper {
 
 	Antragsteller buildAntragsteller(Map<String, Object> headers) {
 		return Antragsteller.builder()
-				.postfachId((String) headers.get(KEY_POSTFACH_ID))
-				.vorname((String) headers.get(KEY_VORNAME))
-				.nachname((String) headers.get(KEY_NACHNAME))
-				.geburtsname((String) headers.get(KEY_GEBURTSNAME))
-				.geburtsort((String) headers.get(KEY_GEBURTSORT))
-				.email((String) headers.get(KEY_EMAIL))
-				.telefon((String) headers.get(KEY_TELEFON))
-				.strasse((String) headers.get(KEY_STRASSE))
-				.plz((String) headers.get(KEY_PLZ))
-				.ort((String) headers.get(KEY_ORT))
+				.postfachId(MapUtils.getString(headers, ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID))
+				.vorname(MapUtils.getString(headers, KEY_VORNAME))
+				.nachname(MapUtils.getString(headers, KEY_NACHNAME))
+				.geburtsname(MapUtils.getString(headers, KEY_GEBURTSNAME))
+				.geburtsort(MapUtils.getString(headers, KEY_GEBURTSORT))
+				.email(MapUtils.getString(headers, KEY_EMAIL))
+				.telefon(MapUtils.getString(headers, KEY_TELEFON))
+				.strasse(MapUtils.getString(headers, KEY_STRASSE))
+				.plz(MapUtils.getString(headers, KEY_PLZ))
+				.ort(MapUtils.getString(headers, KEY_ORT))
 				.build();
 	}
 
 	public boolean isResponsible(FormData formData) {
 		var headers = getHeaders(formData);
-		return headers.containsKey(KEY_POSTFACH_ID) && isPostfachIdNotBlank(headers.get(KEY_POSTFACH_ID));
+		return headers.containsKey(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID)
+				&& isPostfachIdNotBlank(headers.get(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID));
 	}
 
 	@SuppressWarnings("unchecked")
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 ac02afebba1744dce9c70987997fd397fb4ea601..52365312ec979e24d37560740ce9fca8c02db523 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
@@ -95,7 +95,8 @@ class AfmAntragstellerMapper implements AfmEngineBasedMapper {
 	private Optional<Map<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<String, Object>::new);
+				.map(Map.class::cast)
+				.map(LinkedHashMap<String, Object>::new);
 	}
 
 	private Antragsteller.AntragstellerBuilder addAntragstellerData(Antragsteller.AntragstellerBuilder builder,
@@ -162,4 +163,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..5d7224c75ce7ff634737b79d28aeaf6e05931c6d 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
@@ -23,33 +23,53 @@
  */
 package de.ozgcloud.eingang.semantik.enginebased.afm;
 
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
 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 org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
 
+@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/AfmHeaderMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java
index 2984f9a6d257eeae0e1c6e2d361383b37d6a2dbb..0f63ef3686963482d332dd1d844e75ae4d2ec865 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapper.java
@@ -35,7 +35,7 @@ import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataUtils;
 import de.ozgcloud.eingang.common.formdata.FormHeader;
 import de.ozgcloud.eingang.common.formdata.ServiceKonto;
-import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 @Component
 class AfmHeaderMapper implements AfmEngineBasedMapper {
@@ -53,7 +53,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper {
 	static final String SENDER = "t:sender";
 
 	@Autowired
-	private ServiceKontoBuildHelper serviceKontoBuildHelper;
+	private ServiceKontoFactory serviceKontoFactory;
 
 	@Override
 	public FormData parseFormData(FormData formData) {
@@ -84,13 +84,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper {
 	}
 
 	Optional<ServiceKonto> createBayernIdServiceKonto(FormData formData) {
-		var postfachId1 = getPostfachId(formData);
-		return postfachId1.map(postfachId -> serviceKontoBuildHelper.buildBayernIdServiceKonto(postfachId));
-	}
-
-	Optional<String> getPostfachId(FormData formData) {
-		return Optional.ofNullable(getHeaderMap(formData)).map(headers -> headers.get(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID))
-				.map(String.class::cast);
+		return serviceKontoFactory.createBayernIdServiceKonto(getHeaderMap(formData));
 	}
 
 	@SuppressWarnings("unchecked")
@@ -99,7 +93,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper {
 	}
 
 	Optional<ServiceKonto> createOsiServiceKonto(FormData formData) {
-		return getNameId(formData).map(nameId -> serviceKontoBuildHelper.buildOsiServiceKonto(nameId, formData));
+		return getNameId(formData).map(nameId -> serviceKontoFactory.buildOsiServiceKonto(nameId, formData));
 	}
 
 	private Optional<String> getNameId(FormData formData) {
@@ -108,7 +102,7 @@ class AfmHeaderMapper implements AfmEngineBasedMapper {
 
 	private FormData removeMappedData(FormData formData) {
 		return FormDataUtils.from(formData)
-				.remove(ServiceKontoBuildHelper.REST_RESPONSE_NAME)
+				.remove(ServiceKontoFactory.REST_RESPONSE_NAME)
 				.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..d96052447475590512a9ac5cd2280ebe22d0715f
--- /dev/null
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/afm/intelliform/IntelliFormRepresentationAdapter.java
@@ -0,0 +1,145 @@
+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 de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
+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",
+			ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL
+	);
+
+	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 79%
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..b3e75f0cd900dd24d9095c7953939ae450d5db5c 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,14 @@ 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.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.enginebased.EngineBasedSemantikAdapter;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 import lombok.NonNull;
 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);
@@ -36,7 +37,7 @@ public class DFoerdermittelFormBasedMapper implements FormBasedMapper {
 	private static final String KEY_ORGANISATIONS_EINHEIT_ID = "MetaText1";
 
 	@Autowired
-	private ServiceKontoBuildHelper serviceKontoHelper;
+	private ServiceKontoFactory serviceKontoFactory;
 
 	@Override
 	public FormData parseFormData(FormData formData) {
@@ -51,7 +52,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,12 +85,31 @@ 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);
 	}
 
 	private ServiceKonto createServiceKonto(String postfachId) {
-		return serviceKontoHelper.buildOsiServiceKonto(postfachId);
+		return serviceKontoFactory.buildOsiServiceKonto(postfachId);
 	}
 
 	FormData parseFachnachricht(FormData formData, IncomingFile fachnachrichtFile) {
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..6de90deb9ebc890fba588b4f4ea60c983804c300 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
@@ -110,4 +110,4 @@ class FormSolutionsFilesMapper implements FormSolutionsEngineBasedMapper {
 			return ZipAttachmentReader.from(zipFile.getFile(), zipFile.getName());
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java
index 0c8bc2d63bcbf51bdfba7f6963cac424c773c7e8..c2b0de118717b7bb54f0af27ef37e123788f3368 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapper.java
@@ -34,7 +34,7 @@ import org.springframework.stereotype.Component;
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataUtils;
 import de.ozgcloud.eingang.common.formdata.FormHeader;
-import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 @Component
 class FormSolutionsHeaderMapper implements FormSolutionsEngineBasedMapper {
@@ -48,7 +48,7 @@ class FormSolutionsHeaderMapper implements FormSolutionsEngineBasedMapper {
 	public static final String POSTKORBHANDLE = "postkorbhandle";
 
 	@Autowired
-	private ServiceKontoBuildHelper serviceKontoBuildHelper;
+	private ServiceKontoFactory serviceKontoFactory;
 
 	@Override
 	public FormData parseFormData(FormData formData) {
@@ -66,7 +66,7 @@ class FormSolutionsHeaderMapper implements FormSolutionsEngineBasedMapper {
 				.requestId(getRequestId(formData))
 				.formEngineName(FORM_ENGINE_NAME);
 
-		Optional.ofNullable(getPostkorbhandle(formData)).map(serviceKontoBuildHelper::buildOsiServiceKonto).ifPresent(formHeaderBuilder::serviceKonto);
+		Optional.ofNullable(getPostkorbhandle(formData)).map(serviceKontoFactory::buildOsiServiceKonto).ifPresent(formHeaderBuilder::serviceKonto);
 
 		return formHeaderBuilder.build();
 	}
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/FormBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java
index c234ffb21472a2cba5a430312eab492b72982e43..47e053f919675dbbf0f1ab139117ceb65b210193 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedMapper.java
@@ -25,7 +25,7 @@ package de.ozgcloud.eingang.semantik.formbased;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 
-interface FormBasedMapper {
+public interface FormBasedMapper {
 
 	FormData parseFormData(FormData formData);
 
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java
index 823879bd947e3526e7931808bfdbc9b62749264e..9f2d644ab509c5cfce07cca94a33c1b8abefa2ed 100644
--- a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapter.java
@@ -60,4 +60,4 @@ public class FormBasedSemantikAdapter {
 
 	}
 
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragFormBasedMapper.java b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragFormBasedMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..4266a59f2abc000ecfee82567ebb7a04f823df40
--- /dev/null
+++ b/semantik-adapter/src/main/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragFormBasedMapper.java
@@ -0,0 +1,108 @@
+package de.ozgcloud.eingang.semantik.formbased.mantelantrag;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.UnaryOperator;
+import java.util.stream.IntStream;
+
+import org.apache.commons.collections.MapUtils;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
+import de.ozgcloud.eingang.semantik.formbased.FormBasedMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@RequiredArgsConstructor
+@Log4j2
+public class MantelantragFormBasedMapper implements FormBasedMapper {
+	static final String MANTELANTRAG_FORM_ID = "maa_mantelantrag/maa_mantelantrag_pvog";
+	static final String ZUSTELLUNG_NACHRICHTENBROKER_FIELD = "zustellung_nachrichtenbroker";
+	static final String ORGANISATIONSEINHEIT_ID_FIELD = "kontaktsystem_oeid";
+	static final String BEZEICHNUNG_FIELD = "OrganisationseinheitenBEZEICHNUNG";
+	static final String EMAIL_FIELD = "zust_emailadresse";
+	static final String HAUSANSCHRIFT_STRASSE_FIELD = "zust_strasse";
+	static final String HAUSANSCHRIFT_PLZ_FIELD = "zust_postleitzahl";
+	static final String HAUSANSCHRIFT_ORT_FIELD = "zust_ort";
+	static final String TELEFON_FIELD = "telefon";
+
+	private final Environment environment;
+
+	@Override
+	public boolean isResponsible(FormData formData) {
+		return Optional.ofNullable(formData.getHeader())
+				.flatMap(header -> Optional.ofNullable(header.getFormId()))
+				.map(MANTELANTRAG_FORM_ID::equals)
+				.orElse(false);
+	}
+
+	@Override
+	public FormData parseFormData(FormData formData) {
+		try {
+			return adaptFormDataWithPossibleException(formData);
+		} catch (TechnicalException exception) {
+			LOG.warn("Mantelantrag is invalid: %s".formatted(exception.getMessage()));
+			return formData;
+		}
+	}
+
+	FormData adaptFormDataWithPossibleException(FormData formData) {
+		var fieldMap = formData.getFormData();
+		var slotIndex = findSlotIndex(fieldMap);
+		return adaptFormDataWithValueGetter(formData, field -> getFieldByKeyOrEmpty(
+				fieldMap,
+				getNameForSlotIndex(field, slotIndex)
+		));
+	}
+
+	private FormData adaptFormDataWithValueGetter(FormData formData, UnaryOperator<String> getValueOrEmpty) {
+		return formData.toBuilder()
+				.zustaendigeStelle(ZustaendigeStelle.builder()
+						.organisationseinheitenId(getOrganisationseinheitId(getValueOrEmpty))
+						.bezeichnung(getValueOrEmpty.apply(BEZEICHNUNG_FIELD))
+						.email(getValueOrEmpty.apply(EMAIL_FIELD))
+						.hausanschriftStrasse(getValueOrEmpty.apply(HAUSANSCHRIFT_STRASSE_FIELD))
+						.hausanschriftPlz(getValueOrEmpty.apply(HAUSANSCHRIFT_PLZ_FIELD))
+						.hausanschriftOrt(getValueOrEmpty.apply(HAUSANSCHRIFT_ORT_FIELD))
+						.telefon(getValueOrEmpty.apply(TELEFON_FIELD))
+						.build())
+				.build();
+	}
+
+	private String getOrganisationseinheitId(UnaryOperator<String> getValueOrEmpty) {
+		var organisationseinheitId = getValueOrEmpty.apply(ORGANISATIONSEINHEIT_ID_FIELD);
+
+		if (organisationseinheitId.isBlank()) {
+			throw new TechnicalException("OrganistaionseinheitId not found!");
+		}
+
+		return organisationseinheitId;
+	}
+
+	int findSlotIndex(Map<String, Object> fieldMap) {
+		var identifier = environment.getProperty("ozgcloud.xta.identifier");
+		return IntStream.range(0, 3)
+				.filter(slotIndex -> getFieldByKeyOrEmpty(
+								fieldMap,
+								getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex)
+						).equals(identifier)
+				)
+				.findFirst()
+				.orElseThrow(() -> new TechnicalException("No matching nachrichtenbroker address '%s' found!".formatted(identifier)));
+	}
+
+	String getNameForSlotIndex(String name, int slotIndex) {
+		return slotIndex > 0 ? "%s%d".formatted(name, slotIndex + 1) : name;
+	}
+
+	private String getFieldByKeyOrEmpty(Map<String, Object> fieldMap, String key) {
+		return Optional.ofNullable(MapUtils.getString(fieldMap, key))
+				.map(String::trim)
+				.orElse("");
+	}
+
+}
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..754667f0298c9d867846cafee6f28d6b82677fd2 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,35 @@
  */
 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.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 +59,30 @@ class SemantikAdapterTest {
 	@Mock
 	private VorgangService vorgangService;
 
+	@DisplayName("get responsible engine adapters")
+	@Nested
+	class TestGetResponsibleEngineAdapters {
+		@Mock
+		private EngineBasedSemantikAdapter unresponsibleEngineAdapter;
+		@Mock
+		private FormData formData;
+
+		@BeforeEach
+		void mock() {
+			when(unresponsibleEngineAdapter.isResponsible(formData)).thenReturn(false);
+			when(engineAdapter.isResponsible(formData)).thenReturn(true);
+			when(engineAdapters.stream()).thenReturn(Stream.of(engineAdapter, unresponsibleEngineAdapter));
+		}
+
+		@DisplayName("should return responsible")
+		@Test
+		void shouldReturnResponsible() {
+			var foundAdapters = adapter.getResponsibleEngineAdapters(formData);
+
+			assertThat(foundAdapters).isEqualTo(List.of(engineAdapter));
+		}
+	}
+
 	@Nested
 	class TestProcessFormData {
 
@@ -61,10 +95,18 @@ class SemantikAdapterTest {
 
 		@BeforeEach
 		void mockEngineAdapter() {
+			doReturn(List.of(engineAdapter)).when(adapter).getResponsibleEngineAdapters(formData);
 			when(engineAdapter.parseFormData(any())).thenReturn(engineAdapterResponse);
 			when(formAdapter.parseFormData(any())).thenReturn(formAdapterResponse);
 		}
 
+		@Test
+		void shouldCallFindEngineAdapter() {
+			adapter.processFormData(formData);
+
+			verify(adapter).getResponsibleEngineAdapters(formData);
+		}
+
 		@Test
 		void shouldCallEngineAdapter() {
 			adapter.processFormData(formData);
@@ -86,4 +128,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/common/ServiceKontoFactoryTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..66d9d3e302806e9b4aab54e4bba79627488e92fe
--- /dev/null
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ServiceKontoFactoryTest.java
@@ -0,0 +1,303 @@
+package de.ozgcloud.eingang.semantik.common;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+import java.util.Map;
+
+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.Spy;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.FormDataUtils;
+import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory;
+import de.ozgcloud.eingang.common.formdata.ServiceKonto;
+import de.ozgcloud.eingang.common.formdata.ServiceKonto.TrustLevel;
+import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory;
+import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
+import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress;
+import de.ozgcloud.eingang.semantik.enginebased.afm.AfmHeaderTestFactory;
+
+class ServiceKontoFactoryTest {
+
+	@Spy
+	@InjectMocks
+	private ServiceKontoFactory factory;
+
+	@DisplayName("OSI service konto")
+	@Nested
+	class TestOsiServiceKonto {
+
+		private static final FormData FORM_DATA = FormData.builder().formData(AfmHeaderTestFactory.createFormDataMap()).build();
+
+		@DisplayName("with configured postfach")
+		@Nested
+		class TestWithConfiguredPostfach {
+
+			private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create();
+
+			@BeforeEach
+			void mockBuildPostfachAddresses() {
+				doReturn(List.of(POSTFACH_ADDRESS)).when(factory).buildPostfachAddresses(any(), any());
+			}
+
+			@Test
+			void shouldContainsType() {
+				var serviceKonto = getServiceKonto(FORM_DATA);
+
+				assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoFactory.POSTFACH_TYPE_OSI);
+			}
+
+			@Test
+			void shouldContainsPostfachAddresses() {
+				var serviceKonto = getServiceKonto(FORM_DATA);
+
+				assertThat(serviceKonto.getPostfachAddresses()).hasSize(1);
+				assertThat(serviceKonto.getPostfachAddresses().get(0)).isEqualTo(POSTFACH_ADDRESS);
+			}
+
+			@Test
+			void shouldBuildPostfachAddresses() {
+				getServiceKonto(FORM_DATA);
+
+				verify(factory).buildPostfachAddresses(any(), any());
+			}
+		}
+
+		private ServiceKonto getServiceKonto(FormData formData) {
+			return factory.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData);
+		}
+
+		@DisplayName("postfach addresses")
+		@Nested
+		class TestBuildPostfachAddresses {
+
+			@DisplayName("with rest_response_name")
+			@Nested
+			class TestWithRestResponseName {
+
+				@Test
+				void shouldCallBuildAddresses() {
+					getPostfachAddresses();
+
+					verify(factory).buildOsiPostfachV1Address(any(), anyInt());
+				}
+
+				@Test
+				void shouldReturnPostfachAddresses() {
+					var addresses = getPostfachAddresses();
+
+					assertThat(addresses).hasSize(1);
+					assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class);
+					assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId())
+							.isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID);
+					assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoFactory.POSTFACH_VERSION);
+					assertThat(addresses.get(0).getType()).isEqualTo(PostfachAddressTestFactory.POSTFACH_ADDRESS_TYPE);
+				}
+
+				private List<PostfachAddress> getPostfachAddresses() {
+					return buildServiceKonto(FORM_DATA).getPostfachAddresses();
+				}
+			}
+
+			@DisplayName("without rest_response_name")
+			@Nested
+			class TestWithoutRestResponseName {
+
+				private static final FormData FORM_DATA_WITHOUT_REST_RESPONSE_NAME = FormDataUtils.from(FORM_DATA)
+						.remove(ServiceKontoFactory.REST_RESPONSE_NAME).build();
+
+				@Test
+				void shouldBuildDefault() {
+					getPostfachAddresses();
+
+					verify(factory).buildDefault(AfmHeaderTestFactory.POSTFACH_NAME_ID);
+				}
+
+				@Test
+				void shouldReturnPostfachAddresses() {
+					var addresses = getPostfachAddresses();
+
+					assertThat(addresses).hasSize(1);
+
+					assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class);
+
+					assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId())
+							.isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID);
+					assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoFactory.POSTFACH_VERSION);
+					assertThat(addresses.get(0).getType()).isEqualTo(1);
+				}
+
+				private List<PostfachAddress> getPostfachAddresses() {
+					return buildServiceKonto(FORM_DATA_WITHOUT_REST_RESPONSE_NAME).getPostfachAddresses();
+				}
+			}
+
+			private ServiceKonto buildServiceKonto(FormData formData) {
+				return factory.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData);
+			}
+		}
+	}
+
+	@Nested
+	class TestCreateBayernIdServicekonto {
+
+		private final Map<String, Object> formDataHeaders = Map.of(
+				ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, PostfachAddressTestFactory.POSTFACH_ID,
+				ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, ServiceKontoTestFactory.TRUST_LEVEL
+		);
+
+		@DisplayName("should return empty when headers map is null")
+		@Test
+		void shouldReturnEmptyWhenNull() {
+			var serviceKonto = factory.createBayernIdServiceKonto(null);
+
+			assertThat(serviceKonto).isEmpty();
+		}
+
+		@DisplayName("should return empty when postfach id is missing")
+		@Test
+		void shouldReturnEmptyWhenPostfachIdIsMissing() {
+			var serviceKonto = factory.createBayernIdServiceKonto(Map.of());
+
+			assertThat(serviceKonto).isEmpty();
+		}
+
+		@Test
+		void shouldCallIsValidTrustLevel() {
+			factory.createBayernIdServiceKonto(formDataHeaders);
+
+			verify(factory).isValidTrustLevel(formDataHeaders);
+		}
+
+		@Test
+		void shouldCallBuildBayernIdServiceKonto() {
+			factory.createBayernIdServiceKonto(formDataHeaders);
+
+			verify(factory).buildBayernIdServiceKonto(formDataHeaders);
+		}
+
+		@Test
+		void shouldReturnServiceKonto() {
+			var serviceKonto = ServiceKonto.builder().build();
+			doReturn(serviceKonto).when(factory).buildBayernIdServiceKonto(any());
+
+			var result = factory.createBayernIdServiceKonto(formDataHeaders);
+
+			assertThat(result).contains(serviceKonto);
+		}
+
+		@DisplayName("should return empty when trust level has unexpected value")
+		@Test
+		void shouldReturnEmptyWhenTrustLevelCorrupted() {
+			doReturn(false).when(factory).isValidTrustLevel(any());
+
+			var serviceKonto = factory.createBayernIdServiceKonto(formDataHeaders);
+
+			assertThat(serviceKonto).isEmpty();
+		}
+	}
+
+	@Nested
+	class TestIsValidTrustLevel {
+
+		@Test
+		void shouldCallExists() {
+			try (var trustLevelMock = mockStatic(TrustLevel.class)) {
+				isValidTrustLevel();
+
+				trustLevelMock.verify(() -> TrustLevel.exists(ServiceKontoTestFactory.TRUST_LEVEL));
+			}
+		}
+
+		@Test
+		void shouldReturnValue() {
+			try (var trustLevelMock = mockStatic(TrustLevel.class)) {
+				trustLevelMock.when(() -> TrustLevel.exists(any())).thenReturn(true);
+
+				var result = isValidTrustLevel();
+
+				assertThat(result).isTrue();
+			}
+		}
+
+		private boolean isValidTrustLevel() {
+			return factory.isValidTrustLevel(Map.of(ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, ServiceKontoTestFactory.TRUST_LEVEL));
+		}
+	}
+
+	@Nested
+	class TestBuildBayernIdServiceKonto {
+
+		private static final String POSTFACH_ID = "postfach-id";
+		private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create();
+		private static final String TRUST_LEVEL = "STORK-QAA-Level-2";
+
+		private final Map<String, Object> formDataHeaders = Map.of(
+				ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, POSTFACH_ID,
+				ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL, TRUST_LEVEL);
+
+		@Test
+		void shouldSetType() {
+			var serviceKonto = buildBayernIdServiceKonto();
+
+			assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoFactory.POSTFACH_TYPE_BAYERN_ID);
+		}
+
+		@Test
+		void shouldCallBuildPostfachAddress() {
+			buildBayernIdServiceKonto();
+
+			verify(factory).buildPostfachAddress(POSTFACH_ID);
+		}
+
+		@Test
+		void shouldSetPostfachAddress() {
+			doReturn(POSTFACH_ADDRESS).when(factory).buildPostfachAddress(any());
+
+			var serviceKonto = buildBayernIdServiceKonto();
+
+			assertThat(serviceKonto.getPostfachAddresses()).containsOnly(POSTFACH_ADDRESS);
+		}
+
+		@Test
+		void shouldCallGetTrustLevel() {
+			buildBayernIdServiceKonto();
+
+			verify(factory).getTrustLevel(formDataHeaders);
+		}
+
+		@Test
+		void shouldSetTrustLevel() {
+			var serviceKonto = buildBayernIdServiceKonto();
+
+			assertThat(serviceKonto.getTrustLevel()).isEqualTo(TRUST_LEVEL);
+		}
+
+		private ServiceKonto buildBayernIdServiceKonto() {
+			return factory.buildBayernIdServiceKonto(formDataHeaders);
+		}
+	}
+
+	@Nested
+	class TestGetTrustLevel {
+
+		private final Map<String, Object> formDataHeaders = Map.of(ServiceKontoFactory.KEY_BAYERN_ID_TRUST_LEVEL,
+				ServiceKontoTestFactory.TRUST_LEVEL);
+
+		@Test
+		void shouldReturnTrustLevel() {
+			var trustLevel = factory.getTrustLevel(formDataHeaders);
+
+			assertThat(trustLevel).isEqualTo(ServiceKontoTestFactory.TRUST_LEVEL);
+		}
+
+	}
+
+}
\ No newline at end of file
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java
index f6e1fa7e07c716a5b00a059ea8e46c1c35d16116..3f36987c5cfe0ff4b4bb6777c7d4a595c7c43dc4 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/common/ZipAttachmentReaderTest.java
@@ -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
@@ -319,4 +317,4 @@ class ZipAttachmentReaderTest {
 	private static String getTmpDirectoryPath() {
 		return TMP_DIRECTORY_PATH.endsWith("/") ? TMP_DIRECTORY_PATH.substring(0, TMP_DIRECTORY_PATH.length() - 1) : TMP_DIRECTORY_PATH;
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelperTest.java
deleted file mode 100644
index 8d49520d80e2d2ef27042b0dc2399202e44466c9..0000000000000000000000000000000000000000
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/ServiceKontoBuildHelperTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package de.ozgcloud.eingang.semantik.enginebased;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.List;
-
-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.Spy;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.FormDataUtils;
-import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory;
-import de.ozgcloud.eingang.common.formdata.ServiceKonto;
-import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
-import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress;
-import de.ozgcloud.eingang.semantik.enginebased.afm.AfmHeaderTestFactory;
-
-class ServiceKontoBuildHelperTest {
-
-	@Spy
-	@InjectMocks
-	private ServiceKontoBuildHelper helper;
-
-	@DisplayName("OSI service konto")
-	@Nested
-	class TestOsiServiceKonto {
-
-		private static final FormData FORM_DATA = FormData.builder().formData(AfmHeaderTestFactory.createFormDataMap()).build();
-
-		@DisplayName("with configured postfach")
-		@Nested
-		class TestWithConfiguredPostfach {
-
-			private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create();
-
-			@BeforeEach
-			void mockBuildPostfachAddresses() {
-				doReturn(List.of(POSTFACH_ADDRESS)).when(helper).buildPostfachAddresses(any(), any());
-			}
-
-			@Test
-			void shouldContainsType() {
-				var serviceKonto = getServiceKonto(FORM_DATA);
-
-				assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_TYPE_OSI);
-			}
-
-			@Test
-			void shouldContainsPostfachAddresses() {
-				var serviceKonto = getServiceKonto(FORM_DATA);
-
-				assertThat(serviceKonto.getPostfachAddresses()).hasSize(1);
-				assertThat(serviceKonto.getPostfachAddresses().get(0)).isEqualTo(POSTFACH_ADDRESS);
-			}
-
-			@Test
-			void shouldBuildPostfachAddresses() {
-				getServiceKonto(FORM_DATA);
-
-				verify(helper).buildPostfachAddresses(any(), any());
-			}
-		}
-
-		private ServiceKonto getServiceKonto(FormData formData) {
-			return helper.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData);
-		}
-
-		@DisplayName("postfach addresses")
-		@Nested
-		class TestBuildPostfachAddresses {
-
-			@DisplayName("with rest_response_name")
-			@Nested
-			class TestWithRestResponseName {
-
-				@Test
-				void shouldCallBuildAddresses() {
-					getPostfachAddresses();
-
-					verify(helper).buildOsiPostfachV1Address(any(), anyInt());
-				}
-
-				@Test
-				void shouldReturnPostfachAddresses() {
-					var addresses = getPostfachAddresses();
-
-					assertThat(addresses).hasSize(1);
-					assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class);
-					assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId())
-							.isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID);
-					assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_VERSION);
-					assertThat(addresses.get(0).getType()).isEqualTo(PostfachAddressTestFactory.POSTFACH_ADDRESS_TYPE);
-				}
-
-				private List<PostfachAddress> getPostfachAddresses() {
-					return buildServiceKonto(FORM_DATA).getPostfachAddresses();
-				}
-			}
-
-			@DisplayName("without rest_response_name")
-			@Nested
-			class TestWithoutRestResponseName {
-
-				private static final FormData FORM_DATA_WITHOUT_REST_RESPONSE_NAME = FormDataUtils.from(FORM_DATA)
-						.remove(ServiceKontoBuildHelper.REST_RESPONSE_NAME).build();
-
-				@Test
-				void shouldBuildDefault() {
-					getPostfachAddresses();
-
-					verify(helper).buildDefault(AfmHeaderTestFactory.POSTFACH_NAME_ID);
-				}
-
-				@Test
-				void shouldReturnPostfachAddresses() {
-					var addresses = getPostfachAddresses();
-
-					assertThat(addresses).hasSize(1);
-
-					assertThat(addresses.get(0).getIdentifier()).isInstanceOf(StringBasedIdentifier.class);
-
-					assertThat(((StringBasedIdentifier) addresses.get(0).getIdentifier()).getPostfachId())
-							.isEqualTo(AfmHeaderTestFactory.POSTFACH_NAME_ID);
-					assertThat(addresses.get(0).getVersion()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_VERSION);
-					assertThat(addresses.get(0).getType()).isEqualTo(1);
-				}
-
-				private List<PostfachAddress> getPostfachAddresses() {
-					return buildServiceKonto(FORM_DATA_WITHOUT_REST_RESPONSE_NAME).getPostfachAddresses();
-				}
-			}
-
-			private ServiceKonto buildServiceKonto(FormData formData) {
-				return helper.buildOsiServiceKonto(AfmHeaderTestFactory.POSTFACH_NAME_ID, formData);
-			}
-		}
-	}
-
-	@Nested
-	class TestBayernIdServiceKonto {
-
-		private static final String POSTFACH_ID = "postfach-id";
-		private static final PostfachAddress POSTFACH_ADDRESS = PostfachAddressTestFactory.create();
-
-		@Test
-		void shouldSetType() {
-			var serviceKonto = buildBayernIdServiceKonto();
-
-			assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoBuildHelper.POSTFACH_TYPE_BAYERN_ID);
-		}
-
-		@Test
-		void shouldSetPostfachAddress() {
-			doReturn(POSTFACH_ADDRESS).when(helper).buildPostfachAddress(any());
-
-			var serviceKonto = buildBayernIdServiceKonto();
-
-			assertThat(serviceKonto.getPostfachAddresses()).containsOnly(POSTFACH_ADDRESS);
-		}
-
-		ServiceKonto buildBayernIdServiceKonto() {
-			return helper.buildBayernIdServiceKonto(POSTFACH_ID);
-		}
-	}
-}
\ No newline at end of file
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java
index 953ff17d4427885712c3d95f1b9524b0b1dc1bc1..c5c99d30268b7e40f00ef05af208d0a346052bd0 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmAntragstellerHeaderMapperTest.java
@@ -20,6 +20,7 @@ import org.mockito.Spy;
 import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
 import de.ozgcloud.eingang.common.formdata.AntragstellerTestFactory;
 import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 class AfmAntragstellerHeaderMapperTest {
 
@@ -145,7 +146,7 @@ class AfmAntragstellerHeaderMapperTest {
 		@Test
 		void shouldApproveResponsibility() {
 			doReturn(true).when(mapper).isPostfachIdNotBlank(any());
-			doReturn(createHeaders(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, "123")).when(mapper).getHeaders(any());
+			doReturn(createHeaders(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, "123")).when(mapper).getHeaders(any());
 
 			var isResponsible = mapper.isResponsible(formData);
 
@@ -173,8 +174,9 @@ class AfmAntragstellerHeaderMapperTest {
 				assertFalse(isResponsible);
 			}
 
+			@Test
 			void shouldDenyWhenPostfachIdIsBlank() {
-				doReturn(createHeaders(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, null)).when(mapper).getHeaders(any());
+				doReturn(createHeaders(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, null)).when(mapper).getHeaders(any());
 				doReturn(false).when(mapper).isPostfachIdNotBlank(any());
 
 				var isResponsible = mapper.isResponsible(formData);
@@ -215,7 +217,7 @@ class AfmAntragstellerHeaderMapperTest {
 
 		@Test
 		void shouldReturnHeaders() {
-			var headers = createHeaders(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, "123");
+			var headers = createHeaders(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, "123");
 			var formData =  FormData.builder().formData(createHeaders(AfmHeaderMapper.HEADER_FIELD, headers)).build();
 
 			var result = mapper.getHeaders(formData);
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/AfmHeaderMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java
index 93ddc2f4f3e24d4dd2b4c045e6a4d8e39a23086c..7af0dcd5c208e6c3989c0e8be54948e382c45ac6 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderMapperTest.java
@@ -27,7 +27,6 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
-import java.util.Map;
 import java.util.Optional;
 
 import org.junit.jupiter.api.DisplayName;
@@ -40,7 +39,7 @@ import org.mockito.Spy;
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataUtils;
 import de.ozgcloud.eingang.common.formdata.ServiceKonto;
-import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 class AfmHeaderMapperTest {
 
@@ -48,7 +47,7 @@ class AfmHeaderMapperTest {
 	@InjectMocks
 	private AfmHeaderMapper mapper;
 	@Mock
-	private ServiceKontoBuildHelper serviceKontoBuildHelper;
+	private ServiceKontoFactory serviceKontoFactory;
 
 	@DisplayName("Parse form data")
 	@Nested
@@ -124,14 +123,14 @@ class AfmHeaderMapperTest {
 						void shouldCallBuildServiceKontoIfPresent() {
 							parseFormData();
 
-							verify(serviceKontoBuildHelper).buildOsiServiceKonto(any(), eq(FORM_DATA));
+							verify(serviceKontoFactory).buildOsiServiceKonto(any(), eq(FORM_DATA));
 						}
 
 						@Test
 						void shouldNotCallBuildServiceKontoIfNotExists() {
 							mapper.parseFormData(FormDataUtils.from(FORM_DATA).remove(AfmHeaderMapper.POSTFACH_NAME_ID).build());
 
-							verify(serviceKontoBuildHelper, never()).buildOsiServiceKonto(any(), any());
+							verify(serviceKontoFactory, never()).buildOsiServiceKonto(any(), any());
 						}
 					}
 
@@ -155,22 +154,13 @@ class AfmHeaderMapperTest {
 
 						@Test
 						void shouldReturnServiceKonto() {
-							doReturn(Optional.of("id")).when(mapper).getPostfachId(any());
-							when(serviceKontoBuildHelper.buildBayernIdServiceKonto(any())).thenReturn(serviceKonto);
+							when(serviceKontoFactory.createBayernIdServiceKonto(any())).thenReturn(Optional.of(serviceKonto));
 
 							var parsedFormData = mapper.createBayernIdServiceKonto(formData);
 
-							assertThat(parsedFormData).isPresent().get().isEqualTo(serviceKonto);
+							assertThat(parsedFormData).contains(serviceKonto);
 						}
 
-						@Test
-						void shouldNotCallServiceKontoBuildHelper() {
-							doReturn(Optional.empty()).when(mapper).getPostfachId(any());
-
-							mapper.createBayernIdServiceKonto(formData);
-
-							verify(serviceKontoBuildHelper, never()).buildBayernIdServiceKonto(any());
-						}
 					}
 				}
 			}
@@ -190,7 +180,7 @@ class AfmHeaderMapperTest {
 			void shouldRemoveRestResponseName() {
 				var parsedFormData = parseFormData();
 
-				assertThat(parsedFormData.getFormData().get(ServiceKontoBuildHelper.REST_RESPONSE_NAME)).isNull();
+				assertThat(parsedFormData.getFormData().get(ServiceKontoFactory.REST_RESPONSE_NAME)).isNull();
 			}
 
 			private FormData parseFormData() {
@@ -199,28 +189,4 @@ class AfmHeaderMapperTest {
 		}
 	}
 
-	@Nested
-	class TestGetPostfachId {
-
-		@Mock
-		private FormData formData;
-
-		@Test
-		void shouldReturnPostfachId() {
-			doReturn(Map.of(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, AfmAntragstellerTestFactory.POSTFACH_ID)).when(mapper).getHeaderMap(any());
-
-			var postfachId = mapper.getPostfachId(formData);
-
-			assertThat(postfachId).isPresent().get().isEqualTo(AfmAntragstellerTestFactory.POSTFACH_ID);
-		}
-
-		@Test
-		void shouldReturnEmpty() {
-			doReturn(null).when(mapper).getHeaderMap(any());
-
-			var postfachId = mapper.getPostfachId(formData);
-
-			assertThat(postfachId).isEmpty();
-		}
-	}
 }
\ No newline at end of file
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java
index 4cdd6b5f7ed887dbd9841e0d844b5389b25bb366..ff8b85d511d22fd84c3a3302d29c2fe58b31eb78 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/afm/AfmHeaderTestFactory.java
@@ -28,7 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 public class AfmHeaderTestFactory {
 
@@ -57,7 +57,7 @@ public class AfmHeaderTestFactory {
 		var map = new HashMap<String, Object>();
 		map.put(AfmHeaderMapper.HEADER_FIELD, createHeaderMap());
 		map.put(AfmHeaderMapper.POSTFACH_NAME_ID, POSTFACH_NAME_ID);
-		map.put(ServiceKontoBuildHelper.REST_RESPONSE_NAME, List.of(createRestResponseNameMap()));
+		map.put(ServiceKontoFactory.REST_RESPONSE_NAME, List.of(createRestResponseNameMap()));
 
 		return map;
 	}
@@ -81,7 +81,7 @@ public class AfmHeaderTestFactory {
 
 	public static Map<String, Object> createCustomHeaderMap() {
 		var map = new HashMap<String, Object>();
-		map.put(AfmAntragstellerHeaderMapper.KEY_POSTFACH_ID, CUSTOM_POSTFACH_ID);
+		map.put(ServiceKontoFactory.KEY_BAYERN_ID_POSTFACH_ID, CUSTOM_POSTFACH_ID);
 		map.put(AfmAntragstellerHeaderMapper.KEY_VORNAME, CUSTOM_VORNAME);
 		map.put(AfmAntragstellerHeaderMapper.KEY_NACHNAME, CUSTOM_NACHNAME);
 		map.put(AfmAntragstellerHeaderMapper.KEY_GEBURTSNAME, CUSTOM_GEBURTSNAME);
@@ -95,10 +95,10 @@ public class AfmHeaderTestFactory {
 	}
 
 	public static Map<String, Object> createRestResponseNameMap() {
-		return Map.of(ServiceKontoBuildHelper.REST_RESPONSE_NAME_MEMBER_SCOPE, List.of(createRestResponseNameMemberScopeMap()));
+		return Map.of(ServiceKontoFactory.REST_RESPONSE_NAME_MEMBER_SCOPE, List.of(createRestResponseNameMemberScopeMap()));
 	}
 
 	private static Map<String, Object> createRestResponseNameMemberScopeMap() {
-		return Map.of(ServiceKontoBuildHelper.REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE, REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE_VALUE);
+		return Map.of(ServiceKontoFactory.REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE, REST_RESPONSE_NAME_MEMBER_SCOPE_MAILBOX_TYPE_VALUE);
 	}
 }
\ 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 53%
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..05473793842bc54d734988d7cf1ad872d5789b7a 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;
@@ -26,30 +24,30 @@ import de.ozgcloud.eingang.common.formdata.PostfachAddressTestFactory;
 import de.ozgcloud.eingang.common.formdata.ServiceKontoTestFactory;
 import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
 import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
-import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
-class DFoerdermittelFormBasedMapperTest {
+class DFoerdermittelEngineBasedSemantikAdapterTest {
 
 	@Spy
 	@InjectMocks
-	private DFoerdermittelFormBasedMapper mapper;
+	private DFoerdermittelEngineBasedSemantikAdapter adapter;
 
 	@Mock
-	private ServiceKontoBuildHelper serviceKontoHelper;
+	private ServiceKontoFactory serviceKontoFactory;
 
 	@Nested
 	class TestIsResponsible {
 
 		@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);
 		}
 	}
 
@@ -166,12 +174,12 @@ class DFoerdermittelFormBasedMapperTest {
 
 		@BeforeEach
 		void init() {
-			when(serviceKontoHelper.buildOsiServiceKonto(any())).thenReturn(ServiceKontoTestFactory.create());
+			when(serviceKontoFactory.buildOsiServiceKonto(any())).thenReturn(ServiceKontoTestFactory.create());
 		}
 
 		@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,9 +189,9 @@ class DFoerdermittelFormBasedMapperTest {
 
 		@Test
 		void shouldRemovePrefix() {
-			mapper.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
+			adapter.addServiceKonto(DFoerdermittelFormDataTestFactory.create(), DFoerdermittelFormDataTestFactory.createFachnachrichtMap());
 
-			verify(serviceKontoHelper).buildOsiServiceKonto(DFoerdermittelFormDataTestFactory.POSTFACH_ID);
+			verify(serviceKontoFactory).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 9643da03a7980d8332e8a0fe526291b77ab4d424..8683b1c5df30197b6f082d8d0e8a32d27e8c3ec8 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/formsolutions/FormSolutionsHeaderMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java
index 89c782671e7e568ffebc70299df1fc8431499a71..56df1f639ff2bac7f59b24ba6d36bf387227ee59 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/enginebased/formsolutions/FormSolutionsHeaderMapperTest.java
@@ -38,7 +38,7 @@ import org.mockito.Spy;
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataUtils;
 import de.ozgcloud.eingang.common.formdata.FormHeader;
-import de.ozgcloud.eingang.semantik.enginebased.ServiceKontoBuildHelper;
+import de.ozgcloud.eingang.semantik.common.ServiceKontoFactory;
 
 class FormSolutionsHeaderMapperTest {
 
@@ -46,7 +46,7 @@ class FormSolutionsHeaderMapperTest {
 	@InjectMocks
 	private final FormSolutionsHeaderMapper mapper = new FormSolutionsHeaderMapper();
 	@Mock
-	private ServiceKontoBuildHelper serviceKontoBuildHelper;
+	private ServiceKontoFactory serviceKontoFactory;
 
 	@DisplayName("Parse formData")
 	@Nested
@@ -119,7 +119,7 @@ class FormSolutionsHeaderMapperTest {
 				void shouldCallServiceKontoBuildHelper() {
 					buildFormHeader();
 
-					verify(serviceKontoBuildHelper).buildOsiServiceKonto(any());
+					verify(serviceKontoFactory).buildOsiServiceKonto(any());
 				}
 
 				@Test
@@ -128,7 +128,7 @@ class FormSolutionsHeaderMapperTest {
 
 					mapper.buildFormHeader(formDataWithoutPostkorbHandle);
 
-					verify(serviceKontoBuildHelper, never()).buildOsiServiceKonto(any());
+					verify(serviceKontoFactory, never()).buildOsiServiceKonto(any());
 				}
 
 			}
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/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java
index b5d93dca98b934def05ddc44663222dfc9484b9d..7cb39b39ea3e1a7be01f3e256eb8a607724118f6 100644
--- a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/FormBasedSemantikAdapterTest.java
@@ -39,8 +39,6 @@ import org.mockito.Spy;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
-import de.ozgcloud.eingang.semantik.formbased.FormBasedMapper;
-import de.ozgcloud.eingang.semantik.formbased.FormBasedSemantikAdapter;
 
 class FormBasedSemantikAdapterTest {
 
@@ -71,7 +69,7 @@ class FormBasedSemantikAdapterTest {
 		}
 
 		@Test
-		void shouldNotCallMappersIfNOTREsponsible() {
+		void shouldNotCallMapperIfNotResponsible() {
 			when(mapper.isResponsible(any())).thenReturn(false);
 
 			adapter.parseFormData(formData);
@@ -89,4 +87,4 @@ class FormBasedSemantikAdapterTest {
 			assertThat(result).isSameAs(expected);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragFormBasedMapperTest.java b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragFormBasedMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae15e0d29613a93faa2bd5349ab53a38f820b035
--- /dev/null
+++ b/semantik-adapter/src/test/java/de/ozgcloud/eingang/semantik/formbased/mantelantrag/MantelantragFormBasedMapperTest.java
@@ -0,0 +1,333 @@
+package de.ozgcloud.eingang.semantik.formbased.mantelantrag;
+
+import static de.ozgcloud.eingang.semantik.formbased.mantelantrag.MantelantragFormBasedMapper.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.core.env.Environment;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
+import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory;
+import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
+
+class MantelantragFormBasedMapperTest {
+	private final static String TARGET_OEID = "123456";
+	private static final String IDENTIFIER = "gea:test";
+
+	@Spy
+	@InjectMocks
+	private MantelantragFormBasedMapper mapper;
+
+	@Mock
+	private Environment environment;
+
+	@DisplayName("is responsible")
+	@Nested
+	class TestIsResponsible {
+
+		@DisplayName("should be true if mantelantrag form id")
+		@Test
+		void shouldBeTrueIfMantelantragFormId() {
+			var formData = createWithFormId(MANTELANTRAG_FORM_ID);
+
+			var isResponsibleResult = mapper.isResponsible(formData);
+
+			assertThat(isResponsibleResult).isTrue();
+		}
+
+		@DisplayName("should be false if not mantelantrag form id")
+		@Test
+		void shouldBeFalseIfNotMantelantragFormId() {
+			var formData = createWithFormId("any other id");
+
+			var isResponsibleResult = mapper.isResponsible(formData);
+
+			assertThat(isResponsibleResult).isFalse();
+		}
+
+		@DisplayName("should be false if header null")
+		@Test
+		void shouldBeFalseIfHeaderNull() {
+			var formData = FormDataTestFactory.createBuilder()
+					.header(null)
+					.build();
+
+			var isResponsibleResult = mapper.isResponsible(formData);
+
+			assertThat(isResponsibleResult).isFalse();
+		}
+
+		@DisplayName("should be false if form id null")
+		@Test
+		void shouldBeFalseIfFormIdNull() {
+			var formData = FormDataTestFactory.createBuilder()
+					.header(FormHeaderTestFactory.createBuilder()
+							.formId(null)
+							.build())
+					.build();
+
+			var isResponsibleResult = mapper.isResponsible(formData);
+
+			assertThat(isResponsibleResult).isFalse();
+		}
+
+		private FormData createWithFormId(String formId) {
+			return FormDataTestFactory.createBuilder()
+					.header(FormHeaderTestFactory.createBuilder()
+							.formId(formId)
+							.build())
+					.build();
+		}
+	}
+
+	@DisplayName("adapt form data")
+	@Nested
+	class TestAdaptFormData {
+
+		@Mock
+		private FormData formData;
+
+		@Mock
+		private FormData formData2;
+
+		@DisplayName("should return adapted value")
+		@Test
+		void shouldReturnAdaptedValue() {
+			doReturn(formData2).when(mapper).adaptFormDataWithPossibleException(formData);
+
+			var resultFormData = mapper.parseFormData(formData);
+
+			assertThat(resultFormData).isEqualTo(formData2);
+		}
+
+		@DisplayName("should return original value with exception")
+		@Test
+		void shouldReturnOriginalValueWithException() {
+			doThrow(new TechnicalException("some error")).when(mapper).adaptFormDataWithPossibleException(formData);
+
+			var resultFormData = mapper.parseFormData(formData);
+
+			assertThat(resultFormData).isEqualTo(formData);
+		}
+	}
+
+	@DisplayName("adapt form data with possible exception")
+	@Nested
+	class TestAdaptFormDataWithPossibleException {
+
+		private FormData formData;
+
+		private Map<String, Object> fieldMap;
+
+		@BeforeEach
+		void mock() {
+			fieldMap = new HashMap<>(Map.of(
+					getOrganisationseinheitIDFieldName(1), " ",
+					getOrganisationseinheitIDFieldName(2), "",
+					getOrganisationseinheitIDFieldName(10), "1111111"
+			));
+			formData = FormDataTestFactory.createBuilder()
+					.formData(fieldMap)
+					.build();
+		}
+
+		@DisplayName("should keep form data except zustaendigestelle")
+		@Test
+		void shouldKeepFormDataExceptZustaendigestelle() {
+			doReturn(10).when(mapper).findSlotIndex(fieldMap);
+
+			var resultFormData = mapper.parseFormData(formData);
+
+			assertThat(resultFormData.getId()).isEqualTo(formData.getId());
+			assertThat(resultFormData.getHeader()).isEqualTo(formData.getHeader());
+			assertThat(resultFormData.getAntragsteller()).isEqualTo(formData.getAntragsteller());
+		}
+
+		@DisplayName("should map organisationseinheitId")
+		@ParameterizedTest
+		@ValueSource(ints = { 0, 1, 2 })
+		void shouldMapOrganisationseinheitId(int slotIndex) {
+			mockWithOEID(slotIndex, TARGET_OEID);
+
+			var zustaendigeStelle = getAdaptedZustaendigeStelle();
+
+			assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(TARGET_OEID);
+		}
+
+		private String getOrganisationseinheitIDFieldName(int slotIndex) {
+			return mapper.getNameForSlotIndex(ORGANISATIONSEINHEIT_ID_FIELD, slotIndex);
+		}
+
+		@DisplayName("should throw if organistaionseinheitId is missing")
+		@ParameterizedTest
+		@ValueSource(ints = { 0, 1, 2 })
+		void shouldThrowIfOrganistationseinheitIdIsMissing(int slotIndex) {
+			doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap);
+
+			assertThatThrownBy(this::getAdaptedZustaendigeStelle)
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		@DisplayName("should throw if organistationseinheitId is empty")
+		@ParameterizedTest
+		@ValueSource(ints = { 0, 1, 2 })
+		void shouldThrowIfOrganistationseinheitIdIsEmpty(int slotIndex) {
+			mockWithOEID(slotIndex, "");
+
+			assertThatThrownBy(this::getAdaptedZustaendigeStelle)
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		static final String TARGET_OPTIONAL_FIELD_VALUE = "optionalFieldValue";
+
+		static final Map<String, Function<ZustaendigeStelle, String>> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR = Map.of(
+				BEZEICHNUNG_FIELD, ZustaendigeStelle::getBezeichnung,
+				EMAIL_FIELD, ZustaendigeStelle::getEmail,
+				HAUSANSCHRIFT_STRASSE_FIELD, ZustaendigeStelle::getHausanschriftStrasse,
+				HAUSANSCHRIFT_PLZ_FIELD, ZustaendigeStelle::getHausanschriftPlz,
+				HAUSANSCHRIFT_ORT_FIELD, ZustaendigeStelle::getHausanschriftOrt,
+				TELEFON_FIELD, ZustaendigeStelle::getTelefon
+		);
+
+		@DisplayName("should map optional field")
+		@ParameterizedTest
+		@MethodSource("fieldNameAndSlotIndex")
+		void shouldMapOptionalField(int slotIndex, String fieldName) {
+			mockWithSomeOEID(slotIndex);
+			fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), TARGET_OPTIONAL_FIELD_VALUE);
+
+			var zustaendigeStelle = getAdaptedZustaendigeStelle();
+
+			assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEqualTo(TARGET_OPTIONAL_FIELD_VALUE);
+		}
+
+		@DisplayName("should map missing optional fields to empty")
+		@ParameterizedTest
+		@MethodSource("fieldNameAndSlotIndex")
+		void shouldMapMissingOptionalFieldsToEmpty(int slotIndex, String fieldName) {
+			mockWithSomeOEID(slotIndex);
+
+			var zustaendigeStelle = getAdaptedZustaendigeStelle();
+
+			assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty();
+		}
+
+		@DisplayName("should map empty optional fields to empty")
+		@ParameterizedTest
+		@MethodSource("fieldNameAndSlotIndex")
+		void shouldMapEmptyOptionalFieldsToEmpty(int slotIndex, String fieldName) {
+			mockWithSomeOEID(slotIndex);
+			fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), "");
+
+			var zustaendigeStelle = getAdaptedZustaendigeStelle();
+
+			assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty();
+		}
+
+		private String getExpectedByFieldName(ZustaendigeStelle zustaendigeStelle, String fieldName) {
+			var valueExtractor = FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR.get(fieldName);
+			return valueExtractor.apply(zustaendigeStelle);
+		}
+
+		private static Stream<Arguments> fieldNameAndSlotIndex() {
+			return Stream.of(0, 1, 2)
+					.flatMap(slotIndex -> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR
+							.keySet().stream()
+							.map(fieldName -> Arguments.of(slotIndex, fieldName))
+					);
+		}
+
+		private void mockWithSomeOEID(int slotIndex) {
+			mockWithOEID(slotIndex, "some");
+		}
+
+		private void mockWithOEID(int slotIndex, String targetOeid) {
+			fieldMap.put(getOrganisationseinheitIDFieldName(slotIndex), targetOeid);
+			doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap);
+		}
+
+		private ZustaendigeStelle getAdaptedZustaendigeStelle() {
+			var formDataResult = mapper.adaptFormDataWithPossibleException(formData);
+			return formDataResult.getZustaendigeStelle();
+		}
+
+	}
+
+	@DisplayName("find slot index")
+	@Nested
+	class TestFindSlotIndex {
+
+		private Map<String, Object> fieldMap;
+
+		@BeforeEach
+		void mock() {
+			when(environment.getProperty("ozgcloud.xta.identifier")).thenReturn(IDENTIFIER);
+
+			fieldMap = new HashMap<>(Map.of(
+					getZustaendigeStelleName(1), "unknown",
+					getZustaendigeStelleName(2), ""
+			));
+		}
+
+		@DisplayName("should return matching slot")
+		@ParameterizedTest
+		@ValueSource(ints = { 0, 1, 2 })
+		void shouldReturnMatchingSlot(int slotIndex) {
+			fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER);
+
+			var resultSlotIndex = mapper.findSlotIndex(fieldMap);
+
+			assertThat(resultSlotIndex).isEqualTo(slotIndex);
+		}
+
+		private String getZustaendigeStelleName(int slotIndex) {
+			return mapper.getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex);
+		}
+
+		@DisplayName("should throw if no slot matches")
+		@Test
+		void shouldThrowIfNoSlotMatches() {
+			assertThatThrownBy(() -> mapper.findSlotIndex(fieldMap))
+					.isInstanceOf(TechnicalException.class);
+		}
+	}
+
+	@DisplayName("get name for slot index")
+	@Nested
+	class TestGetNameForSlotIndex {
+		@DisplayName("should return name")
+		@ParameterizedTest
+		@MethodSource("nameAndSlotIndexAndExpected")
+		void shouldReturnName(String name, int slotIndex, String expected) {
+			var resultName = mapper.getNameForSlotIndex(name, slotIndex);
+
+			assertThat(resultName).isEqualTo(expected);
+		}
+
+		private static Stream<Arguments> nameAndSlotIndexAndExpected() {
+			return Stream.of(
+					Arguments.of("name", 0, "name"),
+					Arguments.of("name", 1, "name2"),
+					Arguments.of("name", 2, "name3")
+			);
+		}
+	}
+}
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/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl
index 4b1132949310d919a2338612c868c02ad7177325..a66961e50f3068d6dbd68be3bc801d1860195c3a 100644
--- a/src/main/helm/templates/_helpers.tpl
+++ b/src/main/helm/templates/_helpers.tpl
@@ -101,8 +101,9 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }}
 {{- end -}}
 
 {{- define "app.dictToList" -}}
+{{- $customList := list -}}
 {{- range $key, $value := . -}}
-- name: {{ $key }}
-  value: {{ $value }}
+{{- $customList = append $customList (dict "name" $key "value" $value) }}
 {{- end -}}
+{{- $customList | toYaml -}}
 {{- end -}}
\ No newline at end of file
diff --git a/src/main/helm/templates/bindings_type_configmap.yaml b/src/main/helm/templates/bindings_type_configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8e4fbacefd484339668748edd53d0f4503a14ac5
--- /dev/null
+++ b/src/main/helm/templates/bindings_type_configmap.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Release.Name }}-bindings-type
+  namespace: {{ include "app.namespace" . }}
+data:
+  type: |
+    ca-certificates
\ No newline at end of file
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index c7e9bcd8833a52f0e9f1bd7d747ccaadcaf971f3..b3bfd90e14e00c464ea72646affc1408ee4f9923 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -59,6 +59,8 @@ spec:
             app.kubernetes.io/name: {{ .Release.Name }}
       containers:
       - env:
+        - name: SERVICE_BINDING_ROOT
+          value: "/bindings"
         {{- range (.Values.env).grpc }}
         - name: {{ .name }} 
           value: {{ .value }}
@@ -79,7 +81,7 @@ spec:
         - name: grpc_client_vorgang-manager-{{ (.Values.routing).targetVorgangManagerName}}_address
           value: 'vorgang-manager.{{ coalesce (.Values.routing).targetNamespace .Release.Namespace }}:9090'
         - name: grpc_client_vorgang-manager-{{ (.Values.routing).targetVorgangManagerName}}_negotiationType
-          value: {{ (.Values.routing).negotiationType | default "PLAINTEXT" }}
+          value: {{ (.Values.routing).negotiationType | default "TLS" }}
         {{- end }}
         {{- with include "app.getCustomList" . }}
 {{ . | indent 8 }}
@@ -150,9 +152,23 @@ spec:
         volumeMounts:
           - name: temp-dir
             mountPath: "/tmp"
+          - name: namespace-ca-cert
+            mountPath: "/bindings/namespace-certificate"
+            readOnly: true
       volumes:
         - name: temp-dir
           emptyDir: {}
+        - name: namespace-ca-cert
+          projected:
+            sources:
+            - secret:
+                name: {{ include "app.namespace" . }}-ca-cert
+                optional: true
+                items:
+                  - key: ca.crt
+                    path: ca.crt
+            - configMap:
+                name: {{ .Release.Name }}-bindings-type
       dnsConfig: {}
       dnsPolicy: ClusterFirst
       imagePullSecrets:
diff --git a/src/test/helm/bindings_type_test.yaml b/src/test/helm/bindings_type_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f0fa5ade329232c346f328205e67e54f03e1f262
--- /dev/null
+++ b/src/test/helm/bindings_type_test.yaml
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+
+suite: test bindings type configmap
+templates:
+  - templates/bindings_type_configmap.yaml
+release:
+  name: eingang-manager
+  namespace: sh-helm-test
+tests:
+  - it: xta bindings type
+    asserts:
+      - isKind:
+          of: ConfigMap
+      - isAPIVersion:
+          of: v1
+      - equal:
+          path: metadata.name
+          value: eingang-manager-bindings-type
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+      - equal:
+          path: data.type
+          value: ca-certificates
diff --git a/src/test/helm/deployment_bindings_test.yaml b/src/test/helm/deployment_bindings_test.yaml
index 6e48055b01e611b36369c432835f085bebc69b3c..f4e0f24ea4f4e017b21eb33eb0f331ca415a6346 100644
--- a/src/test/helm/deployment_bindings_test.yaml
+++ b/src/test/helm/deployment_bindings_test.yaml
@@ -25,6 +25,9 @@
 suite: deployment bindings
 templates:
   - templates/deployment.yaml
+release:
+  name: eingang-manager
+  namespace: sh-helm-test
 set:
   ozgcloud.environment: test
   imagePullSecret: image-pull-secret
@@ -45,3 +48,28 @@ tests:
             name: temp-dir
             emptyDir: {}
 
+  - it: should have projected namespace-ca-cert volume
+    asserts:
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: namespace-ca-cert
+            projected:
+              sources:
+              - secret:
+                  name: sh-helm-test-ca-cert
+                  optional: true
+                  items:
+                    - key: ca.crt
+                      path: ca.crt
+              - configMap:
+                  name: eingang-manager-bindings-type
+
+  - it: should have namespace-ca-cert volume mount
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: namespace-ca-cert
+            mountPath: "/bindings/namespace-certificate"
+            readOnly: true
\ No newline at end of file
diff --git a/src/test/helm/deployment_env_customList_test.yaml b/src/test/helm/deployment_env_customList_test.yaml
index 8770315d50e1118478b9bf810bc158c1e03664a1..32e81b53357cbab961e85421719a7cb5b274e5e0 100644
--- a/src/test/helm/deployment_env_customList_test.yaml
+++ b/src/test/helm/deployment_env_customList_test.yaml
@@ -34,22 +34,35 @@ tests:
       env.customList:
         - name: my_test_environment_name
           value: "A test value"
+        - name: test_environment
+          value: "B test value"
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
           content:
             name: my_test_environment_name
             value: "A test value"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: test_environment
+            value: "B test value"
   - it: check customList as dict
     set:
       env.customList:
         my_test_environment_name: "A test value"
+        test_environment: "B test value"
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
           content:
             name: my_test_environment_name
             value: "A test value"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: test_environment
+            value: "B test value"
   - it: check customList test value is not set by default
     asserts:
       - notContains:
diff --git a/src/test/helm/deployment_routing_strategy_env.yaml b/src/test/helm/deployment_routing_strategy_env.yaml
index dc9ae515b3ad4c3c4ae977d4700736ff1f6633dc..cd24633dbc3eed6ed59ccd58b70dbf4397b847a1 100644
--- a/src/test/helm/deployment_routing_strategy_env.yaml
+++ b/src/test/helm/deployment_routing_strategy_env.yaml
@@ -49,13 +49,13 @@ tests:
           path: spec.template.spec.containers[0].env
           content:
             name: grpc_client_vorgang-manager-vorgang-manager_negotiationType
-            value: PLAINTEXT
+            value: TLS
   - it: validate routing infos
     set:
       routing:
         routingStrategy: MULTI
         fallbackStrategy: FUNDSTELLE
-        negotiationType: TLS
+        negotiationType: PLAINTEXT
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
@@ -71,4 +71,4 @@ tests:
           path: spec.template.spec.containers[0].env
           content:
             name: grpc_client_vorgang-manager-vorgang-manager_negotiationType
-            value: TLS
\ No newline at end of file
+            value: PLAINTEXT
\ No newline at end of file
diff --git a/xta-adapter/pom.xml b/xta-adapter/pom.xml
index b23ad1bdb3a554de2c5f51dee4499458b5cb1400..496f76e43e1aae88048f354cc69cd7f6cce6b911 100644
--- a/xta-adapter/pom.xml
+++ b/xta-adapter/pom.xml
@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>de.ozgcloud.eingang</groupId>
 		<artifactId>eingang-manager</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
+		<version>2.9.0-SNAPSHOT</version>
 	</parent>
 	<artifactId>xta-adapter</artifactId>
 	<name>Eingangs Adapter - XTA</name>
@@ -81,6 +81,13 @@
 			<artifactId>spring-boot-configuration-processor</artifactId>
 			<optional>true</optional>
 		</dependency>
+		<!-- Test -->
+		<dependency>
+			<groupId>de.ozgcloud.eingang</groupId>
+			<artifactId>common</artifactId>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 	
 	<build>
diff --git a/xta-adapter/readme.md b/xta-adapter/readme.md
index 7dace1573e30605a29e3707bb1eda8af6f4de93b..86a1f9338e7831a8af8c7b4202815531260d25e4 100644
--- a/xta-adapter/readme.md
+++ b/xta-adapter/readme.md
@@ -43,3 +43,6 @@ DEPRECATED, da wir den HostNameVerifier deaktiviert haben: Hosts Datei erzeugen,
 
     127.0.0.1 LI33-0005
 
+# SoapUi Projekt zum manuellen Abrufen des Nachrichtenbrokers
+Im Dokumentation Repo unter `Entwicklungsumgebung/Beistellungen/soapUiXTA` liegt ein SoapUi Projekt,
+dass manuelle XTA-Aufrufe des Nachrichtenbrokers ermöglicht.
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XMLHelper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XMLHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..1eb09f2e7a2fd4e6b194e855f40ea50e110dc044
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XMLHelper.java
@@ -0,0 +1,63 @@
+package de.ozgcloud.eingang.xdomea;
+
+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;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class XMLHelper {
+
+	private static final DocumentBuilder DOCUMENT_BUILDER = createDocumentBuilder();
+	private static final XPathFactory X_PATH_FACTORY = createXPathFactory();
+
+	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);
+		}
+	}
+
+	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 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);
+		}
+	}
+}
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..8408c70c76662633d4ee31716ef2c8b6fad904ee
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXMLValueReader.java
@@ -0,0 +1,59 @@
+package de.ozgcloud.eingang.xdomea;
+
+import static de.ozgcloud.eingang.xdomea.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;
+
+@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..34a807f7001122a0561f319e767c06b08904f25b
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapper.java
@@ -0,0 +1,84 @@
+/*
+ * 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 java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.xta.zip.ZipFileExtractor;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Component
+@RequiredArgsConstructor
+class XtaIncomingFilesMapper {
+
+	private final ZipFileExtractor zipFileExtractor;
+
+	public static final String ZIP_CONTENT_TYPE = "application/zip";
+	static final Predicate<IncomingFile> IS_ZIP_FILE = contentType -> ZIP_CONTENT_TYPE.equals(contentType.getContentType());
+
+	public 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 = zipFileExtractor.extractIncomingFilesSafely(incomingFile);
+				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/java/de/ozgcloud/eingang/xta/zip/LimitedInputStream.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/LimitedInputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee5dc7a8b70e7fe0241a60d94e98ed783f47f66e
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/LimitedInputStream.java
@@ -0,0 +1,42 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class LimitedInputStream extends FilterInputStream {
+	static final String LIMITED_EXCEEDED_MESSAGE = "Read limit exceeded";
+
+	private final long maxSize;
+	long bytesRead;
+
+	public LimitedInputStream(InputStream in, long maxSize) {
+		super(in);
+		this.maxSize = maxSize;
+		this.bytesRead = 0;
+	}
+
+	@Override
+	public int read() throws IOException {
+		var byteValue = super.read();
+		if (byteValue != -1) {
+			updateAndVerifyReadLimit(1);
+		}
+		return byteValue;
+	}
+
+	@Override
+	public int read(byte[] b, int off, int len) throws IOException {
+		return updateAndVerifyReadLimit(super.read(b, off, len));
+	}
+
+	private int updateAndVerifyReadLimit(int newBytesRead) throws IOException {
+		if (newBytesRead != -1) {
+			bytesRead += newBytesRead;
+			if (bytesRead > maxSize) {
+				throw new IOException(LIMITED_EXCEEDED_MESSAGE);
+			}
+		}
+		return newBytesRead;
+	}
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntry.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..fec9014ca3c6ac8c743517d6b45da904b5e9b7aa
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntry.java
@@ -0,0 +1,28 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import lombok.Builder;
+
+@Builder
+record ReadableZipEntry(ZipEntry zipEntry, ZipFile parentZip) {
+	public InputStream getInputStream() throws IOException {
+		return parentZip.getInputStream(zipEntry);
+	}
+
+	public Long getPositiveSize() {
+		var size = zipEntry.getSize();
+		if (size < 0) {
+			throw new TechnicalException("Size of ZIP entry is unknown.");
+		}
+		return size;
+	}
+
+	public String getName() {
+		return zipEntry.getName();
+	}
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractor.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractor.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f162061de832319567338ed51ad2a4c5dc069d3
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractor.java
@@ -0,0 +1,119 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.springframework.stereotype.Component;
+import org.springframework.util.MimeTypeUtils;
+
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+
+// TODO Resolve code duplication with ZipAttachmentReader in semantik-adapter common.zip
+// Note: In contrast to the ZipAttachmentReader, here, the zip file is not included in list of extracted files
+// Further, the suspicious compression ratio ZIP_MAX_THRESHOLD is evaluated on the whole zipFile, instead of individual entries
+@Component
+public class ZipFileExtractor {
+
+	static final double ZIP_MAX_THRESHOLD = 100;
+	static final int ZIP_MAX_TOTAL_SIZE = 500 * 1024 * 1024;
+	static final int ZIP_MAX_ENTRIES = 100;
+
+	public List<IncomingFile> extractIncomingFilesSafely(IncomingFile zipIncomingFile) {
+		var zipFile = zipIncomingFile.getFile();
+		verifyLimits(zipFile);
+		return extractIncomingFiles(zipFile);
+	}
+
+	void verifyLimits(File zipFile) {
+		var uncompressedSize = sumUncompressedEntrySizes(zipFile);
+		verifySizeLimit(uncompressedSize);
+		verifyCompressionRatio(zipFile, uncompressedSize);
+	}
+
+	private void verifySizeLimit(long uncompressedSize) {
+		if (uncompressedSize > getZipMaxTotalSize()) {
+			throw new TechnicalException("Expect uncompressed size %s to be smaller than %d!".formatted(uncompressedSize, getZipMaxTotalSize()));
+		}
+	}
+
+	private void verifyCompressionRatio(File zipFile, long totalSize) {
+		var compressionRatio = (double) totalSize / zipFile.length();
+		if (compressionRatio > ZIP_MAX_THRESHOLD) {
+			throw new TechnicalException(
+					"Expect compression ratio %s to be smaller than %s! A zip bomb attack is suspected!".formatted(compressionRatio,
+							ZIP_MAX_THRESHOLD));
+		}
+	}
+
+	int getZipMaxTotalSize() {
+		return ZIP_MAX_TOTAL_SIZE;
+	}
+
+	Long sumUncompressedEntrySizes(File zipFile) {
+		return mapZipEntries(zipFile, ReadableZipEntry::getPositiveSize)
+				.stream()
+				.mapToLong(Long::longValue)
+				.sum();
+	}
+
+	List<IncomingFile> extractIncomingFiles(File zipFile) {
+		return mapZipEntries(zipFile, this::mapReadableEntryToIncomingFile);
+	}
+
+	private IncomingFile mapReadableEntryToIncomingFile(ReadableZipEntry entry) {
+		File file;
+		try (var inputStream = new LimitedInputStream(entry.getInputStream(), entry.getPositiveSize())) {
+			file = TempFileUtils.writeTmpFile(inputStream);
+		} catch (IOException | de.ozgcloud.common.errorhandling.TechnicalException e) {
+			throw new TechnicalException("Failed reading zip file element %s!".formatted(entry.getName()), e);
+		}
+		return createIncomingFile(file, entry.zipEntry());
+	}
+
+	<T> List<T> mapZipEntries(File zipFile, Function<ReadableZipEntry, T> mappingFunction) {
+		try (ZipFile zip = new ZipFile(zipFile)) {
+			var index = new AtomicInteger();
+			var mappedElements = new ArrayList<T>();
+			zip.stream().forEach(element -> {
+				if (index.getAndIncrement() >= ZIP_MAX_ENTRIES) {
+					throw new TechnicalException("Expect zip files to have at most %d entries!".formatted(ZIP_MAX_ENTRIES));
+				}
+				mappedElements.add(
+						mappingFunction.apply(
+								ReadableZipEntry.builder()
+										.parentZip(zip)
+										.zipEntry(element)
+										.build()
+						)
+				);
+			});
+			return mappedElements;
+		} catch (IOException e) {
+			throw new TechnicalException("Failed reading zip file!", e);
+		}
+	}
+
+	IncomingFile createIncomingFile(File file, ZipEntry zipEntry) {
+		return IncomingFile.builder()
+				.name(zipEntry.getName())
+				.size(zipEntry.getSize())
+				.contentType(getContentType(zipEntry.getName()))
+				.file(file)
+				.build();
+	}
+
+	String getContentType(String name) {
+		Objects.requireNonNull(name);
+		return Objects.requireNonNullElse(URLConnection.guessContentTypeFromName(name), MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);
+	}
+}
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..94f24a83b05a8f49b26ad434438311cb8368f9fe
--- /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
+	private 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.createBuilder().name(FILE_NAME_WITHOUT_SUFFIX).build());
+
+			assertThatThrownBy(() -> fileClassifier.findXdomeaXMLFile(incomingFilesWithout))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		@DisplayName("should return if found")
+		@Test
+		void shouldReturnIfFound() {
+			var targetIncomingFile = IncomingFileTestFactory.createBuilder().name(FILE_NAME_WITH_SUFFIX).build();
+			var incomingFilesWith = List.of(
+					IncomingFileTestFactory.createBuilder().name(FILE_NAME_WITHOUT_SUFFIX).build(),
+					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(name -> IncomingFileTestFactory.createBuilder().name(name).build())
+					.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 moved 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..6a5705a31bc4ea95c96227e291f3d4b3e814da45 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
@@ -1,12 +1,20 @@
 package de.ozgcloud.eingang.xta;
 
 import static org.assertj.core.api.Assertions.*;
-import static org.assertj.core.api.InstanceOfAssertFactories.*;
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Optional;
+
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+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.ArgumentCaptor;
 import org.mockito.Captor;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,104 +23,231 @@ import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.test.context.ActiveProfiles;
 
-import de.ozgcloud.common.test.TestUtils;
 import de.ozgcloud.eingang.Application;
 import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.ServiceKonto;
-import de.ozgcloud.eingang.common.formdata.ServiceKonto.PostfachAddress;
-import de.ozgcloud.eingang.common.formdata.StringBasedIdentifier;
 import de.ozgcloud.eingang.router.VorgangRemoteService;
+import de.ozgcloud.vorgang.vorgang.GrpcEingang;
 
-@SpringBootTest(classes = { Application.class, ActivateXTARunnerConfig.class })
-@ActiveProfiles({ "local", "itcase" })
+@SpringBootTest(classes = {
+		Application.class,
+		XtaITCase.ActivateXTARunnerConfig.class
+})
+@ActiveProfiles({ "itcase" })
 class XtaITCase {
 
-	@MockBean
-	private XtaRemoteService remoteService;
 	@MockBean
 	private VorgangRemoteService vorgangRemoteService;
 
-	@Autowired
-	private XtaRunner runner;
+	@MockBean
+	private XtaRemoteService xtaRemoteService;
+
 	@Captor
-	private ArgumentCaptor<FormData> formDataCaptor;
+	private ArgumentCaptor<FormData> formDataArgumentCaptor;
 
-	@BeforeEach
-	void prepareXtaRemoteService() {
-		when(remoteService.getMessagesMetadata()).thenReturn(XtaMessageMetaDatasAndHeaderTestFactory.create());
+	@Captor
+	private ArgumentCaptor<GrpcEingang> eingangArgumentCaptor;
 
-		when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(
-				XtaMessageTestFactory.createBuilder()
-						.clearMessageFiles()
-						.messageFile(XtaFileTestFactory.withFileContent(TestUtils.loadFile("test_content.zip"), "test_content.zip"))
-						.build());
-	}
+	@Captor
+	private ArgumentCaptor<Optional<String>> organisationseinheitenIdArgumentCaptor;
 
-	@Test
-	void shouldGetMessage() {
-		runner.onApplicationEvent(null);
+	@Autowired
+	private XtaRunner runner;
 
-		verify(remoteService).getMessage(XtaMessageTestFactory.MESSAGE_ID);
+	@DisplayName("run get xta messages")
+	@Nested
+	class TestRunGetXtaMessages {
+		@BeforeEach
+		void setup() {
+			when(vorgangRemoteService.createVorgang(any(), any(), any())).thenReturn("vorgangId(unused)");
+		}
+
+		@DisplayName("should have three representations with pdf")
+		@TestZipFileNamesWithPdf
+		void shouldHaveThreeRepresentationsWithPdf(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var eingang = captureEingang();
+			assertThat(eingang.getNumberOfRepresentations()).isEqualTo(3);
+		}
+
+		@DisplayName("should send two representations without pdf")
+		@TestZipFileNamesWithoutPdf
+		void shouldSendTwoXMLRepresentationsWithoutPdf(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var eingang = captureEingang();
+			assertThat(eingang.getNumberOfRepresentations()).isEqualTo(2);
+		}
+
+		@DisplayName("should have no attachments")
+		@TestZipFileNamesWithoutAnlage
+		void shouldHaveNoAttachments(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var eingang = captureEingang();
+			assertThat(eingang.getNumberOfAttachments()).isZero();
+		}
+
+		@DisplayName("should have one attachment")
+		@TestZipFileNamesWithAnlage
+		void shouldHaveOneAttachment(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var eingang = captureEingang();
+			assertThat(eingang.getNumberOfAttachments()).isEqualTo(1);
+		}
+
+		@DisplayName("should have postfach id")
+		@TestZipFileNamesWithServiceKonto
+		void shouldHavePostfachId(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var serviceKonto = captureEingang()
+					.getHeader()
+					.getServiceKonto();
+			assertThat(serviceKonto).isNotNull();
+			var postfachId = serviceKonto
+					.getPostfachAddresses(0)
+					.getIdentifier()
+					.getProperty(0)
+					.getValue(0);
+			assertThat(postfachId).isEqualTo("4dd01647-b9d9-4775-1b50-08da3d83800a");
+		}
+
+		@DisplayName("should have organistationseinheit ID")
+		@TestZipFileNames
+		void shouldHaveOrganistationseinheitId(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var organisationseinheitenId = captureEingang()
+					.getZustaendigeStelle()
+					.getOrganisationseinheitenId();
+			assertThat(organisationseinheitenId).isEqualTo("9795669");
+		}
+
+		@DisplayName("should have vorgang nummer")
+		@TestZipFileNames
+		void shouldHaveVorgangNummer(String zipFileName) {
+			mockNachrichtenBroker(zipFileName);
+
+			runner.runGetXtaMessages();
+
+			var vorgangNummer = captureEingang().getHeader().getVorgangNummer();
+			assertThat(vorgangNummer).hasSize(9);
+		}
+
+		private GrpcEingang captureEingang() {
+			verify(vorgangRemoteService, times(1))
+					.createVorgang(
+							formDataArgumentCaptor.capture(),
+							eingangArgumentCaptor.capture(),
+							organisationseinheitenIdArgumentCaptor.capture()
+					);
+
+			assertThat(formDataArgumentCaptor.getValue()).isNotNull();
+			assertThat(eingangArgumentCaptor.getValue()).isNotNull();
+			assertThat(organisationseinheitenIdArgumentCaptor.getValue()).isPresent();
+
+			return eingangArgumentCaptor.getValue();
+		}
 	}
 
-	@Test
-	void shouldCloseMessage() {
-		runner.onApplicationEvent(null);
-
-		verify(remoteService, timeout(2000)).close(XtaMessageTestFactory.MESSAGE_ID);
+	private void mockNachrichtenBroker(String zipFileName) {
+		when(xtaRemoteService.getMessage(any(XtaMessageId.class))).thenReturn(
+				XtaResponseTestFactory.createGetMessageResponse(zipFileName)
+		);
+		when(xtaRemoteService.getMessagesMetadata())
+				.thenReturn(XtaResponseTestFactory.createGetStatusListResponse(List.of(zipFileName)));
+		when(xtaRemoteService.getNextMessagesMetadata(any()))
+				.thenReturn(XtaResponseTestFactory.createEmptyGetStatusListResponse());
 	}
 
-	@Test
-	void shouldSend4Representations() {
-		runner.onApplicationEvent(null);
-
-		verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), any(), any());
-		assertThat(formDataCaptor.getValue().getNumberOfRepresentations()).isEqualTo(4);
-		assertThat(formDataCaptor.getValue().getRepresentations()).hasSize(4);
+	@Target({ ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@ParameterizedTest
+	@ValueSource(strings = {
+			"dfoerdermittel_without_anlage.zip",
+			"brauchtumsfeuer_without_anlage.zip",
+			"mantelantrag_without_anlage.zip"
+	})
+	@interface TestZipFileNamesWithoutAnlage {
 	}
 
-	@Test
-	void shouldHavePostfachId() {
-		runner.onApplicationEvent(null);
-
-		var formData = captorFormData();
-
-		assertThat(formData.getHeader().getServiceKonto()).describedAs("ServiceKonto").isNotNull()
-				.extracting(ServiceKonto::getPostfachAddresses).asList().hasSize(1).first()
-				.asInstanceOf(type(PostfachAddress.class))
-				.extracting(PostfachAddress::getIdentifier).isInstanceOf(StringBasedIdentifier.class).asInstanceOf(type(StringBasedIdentifier.class))
-				.extracting(StringBasedIdentifier::getPostfachId).isEqualTo("4dd01647-b9d9-4775-1b50-08da3d83800a");
+	@Target({ ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@ParameterizedTest
+	@ValueSource(strings = {
+			"dfoerdermittel_with_anlage.zip",
+			"brauchtumsfeuer_with_anlage.zip",
+			"mantelantrag_with_anlage.zip"
+	})
+	@interface TestZipFileNamesWithAnlage {
 	}
 
-	@Test
-	void shouldHaveOrganisationsEinheitId() {
-		runner.onApplicationEvent(null);
-
-		var formData = captorFormData();
-
-		assertThat(formData.getZustaendigeStelle().getOrganisationseinheitenId()).isEqualTo("9795669");
+	@Target({ ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@ParameterizedTest
+	@ValueSource(strings = {
+			"dfoerdermittel_without_anlage.zip",
+			"mantelantrag_without_anlage.zip",
+			"brauchtumsfeuer_without_anlage.zip",
+			"dfoerdermittel_with_anlage.zip",
+			"mantelantrag_with_anlage.zip",
+			"brauchtumsfeuer_with_anlage.zip",
+	})
+	@interface TestZipFileNamesWithPdf {
 	}
 
-	@Test
-	void shouldHaveVorgangNummer() {
-		runner.onApplicationEvent(null);
-
-		var formData = captorFormData();
-
-		assertThat(formData.getHeader().getVorgangNummer()).hasSize(9);
+	@Target({ ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@ParameterizedTest
+	@ValueSource(strings = {
+			"waffenschein.zip"
+	})
+	@interface TestZipFileNamesWithoutPdf {
 	}
 
-	private FormData captorFormData() {
-		verify(vorgangRemoteService).createVorgang(formDataCaptor.capture(), any(), any());
-
-		return formDataCaptor.getValue();
+	@Target({ ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@ParameterizedTest
+	@ValueSource(strings = {
+			"dfoerdermittel_without_anlage.zip",
+			"dfoerdermittel_with_anlage.zip",
+	})
+	@interface TestZipFileNamesWithServiceKonto {
 	}
 
-}
+	@Target({ ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@ParameterizedTest
+	@ValueSource(strings = {
+			"dfoerdermittel_without_anlage.zip",
+			"mantelantrag_without_anlage.zip",
+			"brauchtumsfeuer_without_anlage.zip",
+			"dfoerdermittel_with_anlage.zip",
+			"mantelantrag_with_anlage.zip",
+			"brauchtumsfeuer_with_anlage.zip",
+			"waffenschein.zip"
+	})
+	@interface TestZipFileNames {
+	}
 
-class ActivateXTARunnerConfig {
-	@Bean
-	XtaRunner xtaRunner() {
-		return new XtaRunner();
+	static class ActivateXTARunnerConfig {
+		@Bean
+		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..0dfa769d688d5bab27fce58f4673282a7e86caac
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaIncomingFilesMapperTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.Mockito.*;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+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.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
+import de.ozgcloud.eingang.xta.zip.ZipFileExtractor;
+
+class XtaIncomingFilesMapperTest {
+	@Spy
+	@InjectMocks
+	private XtaIncomingFilesMapper mapper;
+
+	@Mock
+	private ZipFileExtractor extractor;
+
+	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 {
+
+		@Mock
+		IncomingFile outFile1;
+
+		@Mock
+		IncomingFile outFile2;
+
+
+		@Test
+		void shouldExtractZipFiles() {
+			var expectedExtractedFiles = List.of(outFile1, outFile2);
+			var zipFile = createTestIncomingFile();
+			when(extractor.extractIncomingFilesSafely(zipFile)).thenReturn(expectedExtractedFiles);
+
+			var extractedFiles = mapper.extractZip(zipFile).toList();
+
+			assertThat(extractedFiles).isEqualTo(expectedExtractedFiles);
+		}
+
+		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();
+	}
+}
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/XtaRemoteServiceITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java
index 6ef62081af72a9e8f549958f3520b98994874822..fdcdd0dbc13ae03a05cf4388939a2a75c8a9e9f9 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaRemoteServiceITCase.java
@@ -54,7 +54,7 @@ class XtaRemoteServiceITCase {
 	class TestGetMessage {
 		@Test
 		void shouldSendRequest() {
-			var result = remoteService.getMessage("urn:de:xta:messageid:dataport_xta_210:81e40808-91c6-4765-aaf4-1aa62fec8be9");
+			var result = remoteService.getMessage("urn:de:xta:messageid:dataport_xta_210:20eb297a-e224-45a0-9376-5ebd4d9bcc9a");
 
 			assertThat(result).isNotNull();
 		}
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/XtaResponseTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e6fed5d2772f9799261cc5b368619c987810c6a
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaResponseTestFactory.java
@@ -0,0 +1,140 @@
+package de.ozgcloud.eingang.xta;
+
+import static de.ozgcloud.eingang.xta.zip.TestZipFileFactory.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.codec.Resources;
+import org.apache.commons.io.IOUtils;
+
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+
+public class XtaResponseTestFactory {
+
+	public static final Map<String, String> MESSAGE_TYPE_BY_ATTACHMENT_FILENAME = Map.of(
+			"mantelantrag_without_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201",
+			"dfoerdermittel_without_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201",
+			"brauchtumsfeuer_without_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201",
+			"versammlungsanzeige.xml", "fim.S17000652.17000652001004",
+			"mantelantrag_with_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201",
+			"dfoerdermittel_with_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201",
+			"brauchtumsfeuer_with_anlage.zip", "Geschaeftsgang.Geschaeftsgang.0201",
+			"waffenschein.zip", "Geschaeftsgang.Geschaeftsgang.0201"
+	);
+
+	private static final Map<String, String> MESSAGE_ID_BY_ATTACHMENT_FILENAME = MESSAGE_TYPE_BY_ATTACHMENT_FILENAME
+			.keySet().stream()
+			.collect(Collectors.toMap(name -> name, name -> generateMessageID()));
+
+	private static String generateMessageID() {
+		return "urn:de:xta:messageid:dataport_xta_210:%s".formatted(UUID.randomUUID().toString());
+	}
+
+	public static XtaMessageMetaDatasAndHeader createEmptyGetStatusListResponse() {
+		return XtaMessageMetaDatasAndHeader.builder()
+				.msgBoxRequestID("testid-empty")
+				.moreMessagesAvailable(false)
+				.messages(Stream.empty())
+				.build();
+	}
+
+	public static XtaMessageMetaDatasAndHeader createGetStatusListResponse(List<String> xtaAttachmentFileNames) {
+		var messageMetaDataItems = xtaAttachmentFileNames.stream()
+				.map(name ->
+						XtaMessageMetaData.builder()
+								.messageId(new XtaMessageId(MESSAGE_ID_BY_ATTACHMENT_FILENAME.get(name)))
+								.messageType(MESSAGE_TYPE_BY_ATTACHMENT_FILENAME.get(name))
+								.origin(ZonedDateTime.now())
+								.delivery(ZonedDateTime.now())
+								.build()
+				)
+				.toList();
+
+		return XtaMessageMetaDatasAndHeader.builder()
+				.msgBoxRequestID("testid-withattachment")
+				.moreMessagesAvailable(true)
+				.messages(messageMetaDataItems.stream())
+				.build();
+	}
+
+	public static XtaMessage createGetMessageResponse(String xtaAttachmentFileName) {
+		File file;
+		try (var inputStream = getAttachmentInputStream(xtaAttachmentFileName)) {
+			file = TempFileUtils.writeTmpFile(inputStream);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+
+		return XtaMessage.builder()
+				.messageFile(XtaFile.builder()
+						.contentType("application/zip")
+						.name(xtaAttachmentFileName)
+						.size(BigInteger.valueOf(file.length()))
+						.file(file)
+						.build())
+				.build();
+	}
+
+	private static InputStream getAttachmentInputStream(String xtaAttachmentFileName) {
+		var attachmentResourcePath = getAttachmentFilePath(xtaAttachmentFileName);
+		if (xtaAttachmentFileName.endsWith(".zip")) {
+			try {
+				return new FileInputStream(
+						createAttachmentZipFile(
+								attachmentResourcePath.replace(".zip", "")));
+			} catch (FileNotFoundException e) {
+				throw new RuntimeException(e);
+			}
+		} else {
+			return Resources.getInputStream(attachmentResourcePath);
+		}
+	}
+
+	private static File createAttachmentZipFile(String attachmentResourceDirectory) {
+		return createTempZipFile(listResourceFileNames(attachmentResourceDirectory)
+				.map(subName -> {
+							try {
+								return TestZipEntry.builder()
+										.name(subName)
+										.content(IOUtils.toByteArray(Resources.getInputStream(attachmentResourceDirectory + "/" + subName)))
+										.build();
+							} catch (IOException e) {
+								throw new RuntimeException(e);
+							}
+						}
+				).toList());
+	}
+
+	private static Stream<String> listResourceFileNames(String resourceDirectoryPath) {
+		try (var inputStream = Resources.getInputStream(resourceDirectoryPath)) {
+			return Arrays.stream(IOUtils.toString(inputStream, StandardCharsets.UTF_8).split("\n"));
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private static String getMessageType(String xtaAttachmentFileName) {
+		return Objects.requireNonNull(
+				MESSAGE_TYPE_BY_ATTACHMENT_FILENAME.get(xtaAttachmentFileName),
+				"Xta-message type for '%s' has to be configured!".formatted(xtaAttachmentFileName)
+		);
+	}
+
+	private static String getAttachmentFilePath(String xtaAttachmentFileName) {
+		return "mock-responses/getMessage/%s/%s".formatted(getMessageType(xtaAttachmentFileName), xtaAttachmentFileName);
+	}
+}
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/java/de/ozgcloud/eingang/xta/zip/LimitedInputStreamTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/LimitedInputStreamTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b01c316d94f4bc994601401daaabacb4e0134efc
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/LimitedInputStreamTest.java
@@ -0,0 +1,141 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import static de.ozgcloud.eingang.xta.zip.LimitedInputStream.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import org.apache.commons.io.IOUtils;
+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 lombok.SneakyThrows;
+
+class LimitedInputStreamTest {
+
+	private static final int READ_LIMIT = 10;
+	private static final String STRING_WITH_READ_LIMIT_LENGTH = "A".repeat(READ_LIMIT);
+	private static final String STRING_WITH_MORE_THAN_READ_LIMIT_LENGTH = "B".repeat(READ_LIMIT + 1);
+
+	private LimitedInputStream limitedInputStream;
+
+	private InputStream createStringInputSteam(String string) {
+		return new ByteArrayInputStream(string.getBytes());
+	}
+
+	@SneakyThrows
+	private String readInputStreamToString(InputStream inputStream) {
+		return IOUtils.toString(inputStream, Charset.defaultCharset());
+	}
+
+	@SneakyThrows
+	@DisplayName("should succeed if read limit is not exceeded")
+	@Test
+	void shouldSucceedIfReadLimitIsNotExceeded() {
+		limitedInputStream = new LimitedInputStream(createStringInputSteam(STRING_WITH_READ_LIMIT_LENGTH), READ_LIMIT);
+
+		var outputString = readInputStreamToString(limitedInputStream);
+
+		assertThat(outputString).isEqualTo(STRING_WITH_READ_LIMIT_LENGTH);
+	}
+
+	@DisplayName("should fail if read limit is exceeded")
+	@Test
+	void shouldFailIfReadLimitIsExceeded() {
+		limitedInputStream = new LimitedInputStream(createStringInputSteam(STRING_WITH_MORE_THAN_READ_LIMIT_LENGTH), READ_LIMIT);
+
+		assertThatThrownBy(() -> readInputStreamToString(limitedInputStream))
+				.isInstanceOf(IOException.class)
+				.hasMessage(LIMITED_EXCEEDED_MESSAGE);
+	}
+
+	@DisplayName("read")
+	@Nested
+	class TestRead {
+
+		@SneakyThrows
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			limitedInputStream = createLimitedInputStream();
+
+			var result = limitedInputStream.read();
+			assertThat(result).isEqualTo(STRING_WITH_READ_LIMIT_LENGTH.getBytes()[0]);
+		}
+
+		@SneakyThrows
+		@DisplayName("should advance bytesRead")
+		@Test
+		void shouldAdvanceBytesRead() {
+			limitedInputStream = createLimitedInputStream();
+			limitedInputStream.bytesRead = READ_LIMIT - 1;
+
+			limitedInputStream.read();
+			assertThat(limitedInputStream.bytesRead).isEqualTo(READ_LIMIT);
+		}
+
+		@DisplayName("should throw if exceeded")
+		@Test
+		void shouldThrowIfExceeded() {
+			limitedInputStream = createLimitedInputStreamWithExceeding();
+			limitedInputStream.bytesRead = READ_LIMIT;
+
+			assertThatThrownBy(() -> limitedInputStream.read()).isInstanceOf(IOException.class);
+		}
+
+	}
+
+	@DisplayName("read into buffer")
+	@Nested
+	class TestReadIntoBuffer {
+		private byte[] buffer;
+
+		@BeforeEach
+		void mock() {
+			buffer = new byte[READ_LIMIT];
+		}
+
+		@SneakyThrows
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			limitedInputStream = createLimitedInputStream();
+
+			var result = limitedInputStream.read(buffer);
+
+			assertThat(result).isEqualTo(READ_LIMIT);
+		}
+
+		@SneakyThrows
+		@DisplayName("should advance bytesRead")
+		@Test
+		void shouldAdvanceBytesRead() {
+			limitedInputStream = createLimitedInputStream();
+
+			limitedInputStream.read(buffer);
+			assertThat(limitedInputStream.bytesRead).isEqualTo(READ_LIMIT);
+		}
+
+		@DisplayName("should throw if exceeded")
+		@Test
+		void shouldThrowIfExceeded() {
+			limitedInputStream = createLimitedInputStreamWithExceeding();
+			limitedInputStream.bytesRead = 1;
+
+			assertThatThrownBy(() -> limitedInputStream.read(buffer)).isInstanceOf(IOException.class);
+		}
+	}
+
+	private LimitedInputStream createLimitedInputStream() {
+		return new LimitedInputStream(createStringInputSteam(STRING_WITH_READ_LIMIT_LENGTH), READ_LIMIT);
+	}
+
+	private LimitedInputStream createLimitedInputStreamWithExceeding() {
+		return new LimitedInputStream(createStringInputSteam(STRING_WITH_MORE_THAN_READ_LIMIT_LENGTH), READ_LIMIT);
+	}
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntryTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5bfea0888cf15d8791777a8bf826e13868c489c
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ReadableZipEntryTest.java
@@ -0,0 +1,80 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+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.Mock;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import lombok.SneakyThrows;
+
+class ReadableZipEntryTest {
+
+	@Mock
+	ZipEntry zipEntry;
+
+	@Mock
+	ZipFile zipFile;
+
+	private ReadableZipEntry readableZipEntry;
+
+	@BeforeEach
+	void mock() {
+		readableZipEntry = ReadableZipEntry.builder()
+				.zipEntry(zipEntry)
+				.parentZip(zipFile)
+				.build();
+
+	}
+
+	@DisplayName("get input stream")
+	@Nested
+	class TestGetInputStream {
+		@Mock
+		private InputStream inputStream;
+
+		@SneakyThrows
+		@DisplayName("should return input stream")
+		@Test
+		void shouldReturnInputStream() {
+			when(zipFile.getInputStream(zipEntry)).thenReturn(inputStream);
+
+			var inputStreamResult = readableZipEntry.getInputStream();
+
+			assertThat(inputStreamResult).isEqualTo(inputStream);
+		}
+	}
+
+	@DisplayName("get positive size")
+	@Nested
+	class TestGetPositiveSize {
+		@DisplayName("should return size")
+		@Test
+		void shouldReturnSize() {
+			var size = 123L;
+			when(zipEntry.getSize()).thenReturn(size);
+
+			var sizeResult = readableZipEntry.getPositiveSize();
+
+			assertThat(sizeResult).isEqualTo(size);
+		}
+
+		@DisplayName("should throw if size is negative")
+		@Test
+		void shouldThrowIfSizeIsNegative() {
+			var size = -1L;
+			when(zipEntry.getSize()).thenReturn(size);
+
+			assertThatThrownBy(() -> readableZipEntry.getPositiveSize()).isInstanceOf(TechnicalException.class);
+		}
+
+	}
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/TestZipFileFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/TestZipFileFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ac1b3595af4ae63e720a765d8fdced3a9730906
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/TestZipFileFactory.java
@@ -0,0 +1,113 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.io.IOUtils;
+
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+import lombok.Builder;
+import lombok.Getter;
+
+public class TestZipFileFactory {
+
+	private static final String EXPANDED_ENTRY_NAME = "bomb.txt";
+
+	@Builder
+	@Getter
+	public static class TestZipEntry {
+		private String name;
+		private byte[] content;
+	}
+
+	public static File createTempZipFile(List<TestZipEntry> testZipEntries) {
+		var file = TempFileUtils.createTmpFile().toFile();
+		try (var zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) {
+			for (TestZipEntry entry : testZipEntries) {
+				zipOutputStream.putNextEntry(new ZipEntry(entry.getName()));
+				zipOutputStream.write(entry.getContent());
+				zipOutputStream.closeEntry();
+			}
+			return file;
+		} catch (IOException e) {
+			throw new RuntimeException("Failed to create temporary zip file", e);
+		}
+	}
+
+	public static File createTempZipBomb(int maxTotalSize) {
+		return overwriteFileWithZipEntrySize(
+				createTempZipWithSingleEntry(maxTotalSize * 2),
+				maxTotalSize
+		);
+	}
+
+	private static File createTempZipWithSingleEntry(int entrySize) {
+		var file = TempFileUtils.createTmpFile().toFile();
+		try (var zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) {
+			var entry = new ZipEntry(EXPANDED_ENTRY_NAME);
+			var content = "A".repeat(entrySize).getBytes();
+
+			zipOutputStream.putNextEntry(entry);
+			zipOutputStream.write(content);
+			zipOutputStream.closeEntry();
+
+		} catch (IOException e) {
+			throw new RuntimeException("Failed to create temporary zip file", e);
+		}
+		return file;
+	}
+
+	private static File overwriteFileWithZipEntrySize(File file, int newSize) {
+		try {
+			var zipFileBytes = IOUtils.toByteArray(new FileInputStream(file));
+			overwriteZipEntrySize(zipFileBytes, EXPANDED_ENTRY_NAME, newSize);
+
+			// Write the adjusted ZIP content back to the file
+			try (var fos = new FileOutputStream(file)) {
+				fos.write(zipFileBytes);
+			}
+		} catch (IOException e) {
+			throw new RuntimeException("Failed to adjust size header of zip file", e);
+		}
+		return file;
+	}
+
+	private static void overwriteZipEntrySize(byte[] zipFileBytes, String entryName, int newSize) throws IOException {
+		// Modify the uncompressed size entry size in the central directory structure (which is located at the end)
+		// Zip structure spec: https://www.iana.org/assignments/media-types/application/zip
+		var entryNameBytes = entryName.getBytes();
+
+		var lastIndexOfEntryName = findLastStartIndex(zipFileBytes, entryNameBytes);
+		if (lastIndexOfEntryName == -1) {
+			throw new IOException("ZIP entry not found: " + entryName);
+		}
+		var uncompressedSizeFieldStartOffset = lastIndexOfEntryName - (4 * 2 + 5 * 2 + 4);
+		writeIntToByteArray(newSize, zipFileBytes, uncompressedSizeFieldStartOffset);
+	}
+
+	private static void writeIntToByteArray(int value, byte[] array, int offset) {
+		array[offset] = (byte) (value & 0xFF);
+		array[offset + 1] = (byte) ((value >> 8) & 0xFF);
+		array[offset + 2] = (byte) ((value >> 16) & 0xFF);
+		array[offset + 3] = (byte) ((value >> 24) & 0xFF);
+	}
+
+	private static int findLastStartIndex(byte[] haystack, byte[] needle) {
+		var matchOffset = 0;
+		for (var i = haystack.length - 1; i >= needle.length; i--) {
+			if (haystack[i] == needle[needle.length - 1 - matchOffset]) {
+				if (++matchOffset == needle.length) {
+					return i;
+				}
+			} else {
+				matchOffset = 0;
+			}
+		}
+		return -1;
+	}
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractorTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d23838973567f333510c7b14d5ae4536cd119655
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/zip/ZipFileExtractorTest.java
@@ -0,0 +1,371 @@
+package de.ozgcloud.eingang.xta.zip;
+
+import static de.ozgcloud.eingang.xta.zip.TestZipFileFactory.*;
+import static de.ozgcloud.eingang.xta.zip.ZipFileExtractor.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.IntStream;
+import java.util.zip.ZipEntry;
+
+import org.apache.commons.lang3.StringUtils;
+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 org.springframework.util.MimeTypeUtils;
+
+import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import lombok.SneakyThrows;
+
+class ZipFileExtractorTest {
+
+	@Spy
+	@InjectMocks
+	private ZipFileExtractor extractor;
+
+	@DisplayName("extract incoming files safely")
+	@Nested
+	class TestExtractIncomingFilesWithSizeLimit {
+		@Mock
+		IncomingFile incomingZipFile;
+
+		@Mock
+		File zipFile;
+
+		@Mock
+		IncomingFile outIncomingFile;
+
+		List<IncomingFile> outIncomingFiles;
+
+		@BeforeEach
+		void mock() {
+			outIncomingFiles = List.of(outIncomingFile);
+
+			when(incomingZipFile.getFile()).thenReturn(zipFile);
+			doNothing().when(extractor).verifyLimits(zipFile);
+
+			doReturn(outIncomingFiles).when(extractor).extractIncomingFiles(zipFile);
+		}
+
+		@DisplayName("should call verify limits")
+		@Test
+		void shouldCallVerifySizeLimit() {
+			extractor.extractIncomingFilesSafely(incomingZipFile);
+
+			verify(extractor).verifyLimits(zipFile);
+		}
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			var output = extractor.extractIncomingFilesSafely(incomingZipFile);
+
+			assertThat(output).isEqualTo(outIncomingFiles);
+		}
+	}
+
+	@DisplayName("verify limits")
+	@Nested
+	class TestVerifyLimits {
+		@Mock
+		File zipFile;
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			when(zipFile.length()).thenReturn((long) ZIP_MAX_TOTAL_SIZE / 2);
+			doReturn((long) ZIP_MAX_TOTAL_SIZE).when(extractor).sumUncompressedEntrySizes(zipFile);
+
+			extractor.verifyLimits(zipFile);
+		}
+
+		@DisplayName("should throw if size limit exceeded")
+		@Test
+		void shouldThrowIfSizeLimitExceeded() {
+			doReturn((long) ZIP_MAX_TOTAL_SIZE + 1).when(extractor).sumUncompressedEntrySizes(zipFile);
+
+			assertThatThrownBy(() -> extractor.verifyLimits(zipFile))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		@DisplayName("should throw if ratio exceeded")
+		@Test
+		void shouldThrowIfRatioExceeded() {
+			when(zipFile.length()).thenReturn(1L);
+			doReturn((long) ZIP_MAX_THRESHOLD + 1).when(extractor).sumUncompressedEntrySizes(zipFile);
+
+			assertThatThrownBy(() -> extractor.verifyLimits(zipFile))
+					.isInstanceOf(TechnicalException.class);
+		}
+	}
+
+	@DisplayName("extract incoming files")
+	@Nested
+	class TestExtractIncomingFiles {
+
+		private File zipFile;
+
+		@BeforeEach
+		void mock() {
+			zipFile = createTempZipFile(fromMap(Map.of(
+					"file1.pdf", "file content1",
+					"file2.xml", "<root></root>",
+					"file3.png", ""
+			)));
+		}
+
+		@DisplayName("should contain content")
+		@Test
+		void shouldContainContent() {
+			var extractedFiles = extractor.extractIncomingFiles(zipFile);
+
+			var contents = extractedFiles.stream().map(f -> {
+				try {
+					return Files.readString(f.getFile().toPath());
+				} catch (IOException e) {
+					throw new RuntimeException(e);
+				}
+			}).toList();
+			assertThat(contents).containsExactlyInAnyOrder("file content1", "<root></root>", "");
+		}
+
+		@DisplayName("should have names")
+		@Test
+		void shouldHaveNames() {
+			var extractedFiles = extractor.extractIncomingFiles(zipFile);
+
+			var names = extractedFiles.stream().map(IncomingFile::getName).toList();
+			assertThat(names).containsExactlyInAnyOrder("file1.pdf", "file2.xml", "file3.png");
+		}
+
+		@DisplayName("should have content types")
+		@Test
+		void shouldHaveContentTypes() {
+			var extractedFiles = extractor.extractIncomingFiles(zipFile);
+
+			var names = extractedFiles.stream().map(IncomingFile::getContentType).toList();
+			assertThat(names).containsExactlyInAnyOrder("application/pdf", "application/xml", "image/png");
+		}
+
+		private List<TestZipEntry> fromMap(Map<String, String> entries) {
+			return entries.entrySet().stream().map(kv -> TestZipEntry.builder()
+							.name(kv.getKey())
+							.content(kv.getValue().getBytes(StandardCharsets.UTF_8))
+							.build())
+					.toList();
+		}
+	}
+
+	@DisplayName("extract zip bomb")
+	@Nested
+	class TestExtractZipBomb {
+		private static final int SMALLER_MAX_ZIP_FILE_SIZE = 2 * 1024;
+
+		@DisplayName("should throw with too many entries")
+		@Test
+		void shouldThrow() {
+			var zipFile = createIncomingFile(createTempZipFile(IntStream.range(0, ZIP_MAX_ENTRIES + 1).mapToObj(i -> TestZipEntry.builder()
+					.name("file%d.txt".formatted(i))
+					.content(toBytes("A".repeat(2)))
+					.build()
+			).toList()));
+
+			assertThatThrownBy(() -> extractor.extractIncomingFilesSafely(zipFile))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		@SneakyThrows
+		@DisplayName("should throw with fake getSize")
+		@Test
+		void shouldThrowWithFakeGetSize() {
+			doReturn(SMALLER_MAX_ZIP_FILE_SIZE).when(extractor).getZipMaxTotalSize();
+			var zipBomb = createIncomingFile(createTempZipBomb(SMALLER_MAX_ZIP_FILE_SIZE));
+
+			assertThatThrownBy(() -> extractor.extractIncomingFilesSafely(zipBomb))
+					.isInstanceOf(TechnicalException.class)
+					.hasRootCauseMessage(LimitedInputStream.LIMITED_EXCEEDED_MESSAGE);
+		}
+
+		@DisplayName("should throw with too large size")
+		@Test
+		void shouldThrowWithTooLargeSize() {
+			doReturn(SMALLER_MAX_ZIP_FILE_SIZE).when(extractor).getZipMaxTotalSize();
+			var zipFile = createIncomingFile(createTempZipFile(List.of(TestZipEntry.builder()
+					.name("toolargefile.txt")
+					.content(toBytes("A".repeat(SMALLER_MAX_ZIP_FILE_SIZE + 1)))
+					.build()
+			)));
+
+			assertThatThrownBy(() -> extractor.extractIncomingFilesSafely(zipFile))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		private IncomingFile createIncomingFile(File file) {
+			return IncomingFile.builder()
+					.file(file)
+					.build();
+		}
+	}
+
+	@DisplayName("create incoming file")
+	@Nested
+	class TestCreateIncomingFile {
+		@Mock
+		File file;
+
+		@Mock
+		ZipEntry zipEntry;
+
+		private static final String NAME = "filename.name";
+		private static final Long SIZE = 5L;
+		private static final String CONTENT_TYPE = "some/content";
+
+		@BeforeEach
+		void mock() {
+			when(zipEntry.getName()).thenReturn(NAME);
+			when(zipEntry.getSize()).thenReturn(SIZE);
+			doReturn(CONTENT_TYPE).when(extractor).getContentType(NAME);
+		}
+
+		@DisplayName("should have name")
+		@Test
+		void shouldHaveName() {
+			var incomingFile = create();
+
+			assertThat(incomingFile.getName()).isEqualTo(NAME);
+		}
+
+		@DisplayName("should have size")
+		@Test
+		void shouldHaveSize() {
+			var incomingFile = create();
+
+			assertThat(incomingFile.getSize()).isEqualTo(SIZE);
+		}
+
+		@DisplayName("should have content type")
+		@Test
+		void shouldHaveContentType() {
+			var incomingFile = create();
+
+			assertThat(incomingFile.getContentType()).isEqualTo(CONTENT_TYPE);
+		}
+
+		@DisplayName("should have file")
+		@Test
+		void shouldHaveFile() {
+			var incomingFile = create();
+
+			assertThat(incomingFile.getFile()).isEqualTo(file);
+		}
+
+		private IncomingFile create() {
+			return extractor.createIncomingFile(file, zipEntry);
+		}
+	}
+
+	@DisplayName("sum uncompressed entry size")
+	@Nested
+	class TestSumUncompressedEntrySize {
+		@DisplayName("should return size")
+		@Test
+		void shouldReturnSize() {
+			var sizes = IntStream.range(100, 110).boxed().toList();
+			var expectedSum = sizes.stream().mapToLong(Integer::longValue).sum();
+			var zipFile = createTempZipFile(sizes.stream()
+					.map(size -> TestZipEntry.builder()
+							.name("somefilewithsize%d".formatted(size))
+							.content(toBytes("A".repeat(size)))
+							.build()
+					).toList());
+
+			var sum = extractor.sumUncompressedEntrySizes(zipFile);
+
+			assertThat(sum).isEqualTo(expectedSum);
+		}
+	}
+
+	@Nested
+	class TestContentType {
+
+		@Test
+		void shouldReturnDefaultWhenNullString() {
+			assertThrows(NullPointerException.class, () -> extractor.getContentType(null));
+		}
+
+		@Test
+		void shouldReturnDefaultWhenEmptyString() {
+			var contentType = extractor.getContentType(StringUtils.EMPTY);
+
+			assertThat(contentType).isEqualTo(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);
+		}
+
+		@Test
+		void shouldReturnDefaultWhenSpaceString() {
+			var contentType = extractor.getContentType(StringUtils.SPACE);
+
+			assertThat(contentType).isEqualTo(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);
+		}
+
+		@Test
+		void shouldGetContentType() {
+			var fileNames = List.of("1.xml", "2.txt");
+
+			var contentTypes = fileNames.stream().map(extractor::getContentType).toList();
+
+			assertThat(contentTypes).containsExactlyInAnyOrder(MimeTypeUtils.APPLICATION_XML_VALUE, MimeTypeUtils.TEXT_PLAIN_VALUE);
+		}
+	}
+
+	@DisplayName("map zip entries")
+	@Nested
+	class TestMapZipEntries {
+
+		@DisplayName("should throw if max entries exceeded")
+		@Test
+		void shouldThrowIfMaxEntriesExceeded() {
+			var zipWithTooManyEntries = createTempZipFile(IntStream.range(0, ZIP_MAX_ENTRIES + 1)
+					.mapToObj(i -> TestZipEntry.builder()
+							.name("test%d.txt".formatted(i))
+							.content(toBytes("test file %d".formatted(i)))
+							.build()
+					).toList());
+
+			assertThatThrownBy(() -> extractor.mapZipEntries(zipWithTooManyEntries, entry -> null))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		@DisplayName("should map with mapping function")
+		@Test
+		void shouldMapWithMappingFunction() {
+			var expectedNumberList = IntStream.range(0, ZIP_MAX_ENTRIES).boxed().toList();
+			var zipFile = createTempZipFile(expectedNumberList.stream()
+					.map(i -> TestZipEntry.builder()
+							.name("%d".formatted(i))
+							.content(toBytes("some content"))
+							.build()
+					).toList());
+
+			var numberList = extractor.mapZipEntries(zipFile, entry -> Integer.parseInt(entry.getName()));
+
+			assertThat(numberList).isEqualTo(expectedNumberList);
+		}
+	}
+
+	private byte[] toBytes(String string) {
+		return string.getBytes(StandardCharsets.UTF_8);
+	}
+
+}
diff --git a/xta-adapter/src/test/resources/application-itcase.yml b/xta-adapter/src/test/resources/application-itcase.yml
index fa5c5d86fbded8b86eaf4361fee63b6e16e199c1..e2862c67d31c9bfe1ec689b41402e29d1c9da0de 100644
--- a/xta-adapter/src/test/resources/application-itcase.yml
+++ b/xta-adapter/src/test/resources/application-itcase.yml
@@ -1,6 +1,21 @@
 ozgcloud:
   xta:
+    identifier: afmsh:010600000000_Online-Dienste
+    server:
+      address: localhost:3000
+      name: LI33-0005
+      protocol: https
     keystore:
       file: classpath:xtaTestStore.p12
       password: <geheim>
-    identifier: gae:noreply@ozg-sh.de
\ No newline at end of file
+  adapter:
+    targetVorgangManagerName: itcase
+    fallbackStrategy: DENY
+    routingStrategy: SINGLE
+
+
+grpc:
+  client:
+    vorgang-manager-itcase:
+      address: in-process:vorgang-manager-itcase
+      negotiationType: PLAINTEXT
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/60b6753a-23a8-4552-ae82-36ed96f63e03_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/60b6753a-23a8-4552-ae82-36ed96f63e03_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9623996ed13c169c65fdc7b49b98671a4ce5f6ee
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/60b6753a-23a8-4552-ae82-36ed96f63e03_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1">
+  <xdomea:Kopf>
+    <xdomea:ProzessID>60b6753a-23a8-4552-ae82-36ed96f63e03</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-05-17T15:35:54.560+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>30714b70-3ba3-4f32-a36a-4990162f14bb</xdomea:ID>
+      </xdomea:Identifikation>
+      <xdomea:AllgemeineMetadaten>
+        <xdomea:Betreff>Brauchtumsfeuer NB Anbindung Test</xdomea:Betreff>
+        <xdomea:Kennzeichen>20240517561130590306</xdomea:Kennzeichen>
+      </xdomea:AllgemeineMetadaten>
+      <xdomea:Posteingangsdatum>2024-05-17</xdomea:Posteingangsdatum>
+      <xdomea:Typ>btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb</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>73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml</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>2ef19b50-2d00-4cb0-8318-e3422ab27b86_PDF-Antrag.pdf</xdomea:Dateiname>
+          </xdomea:Primaerdokument>
+        </xdomea:Format>
+      </xdomea:Version>
+    </xdomea:Dokument>
+  </xdomea:Hauptobjekt>
+  <xdomea:ExternerGeschaeftsgang>
+    <xdomea:Identifikation>
+      <xdomea:ID>6c89a915-791b-4e9f-a06b-a23a16925c34</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-05-17</xdomea:Erstellungsdatum>
+        <xdomea:Erstellungsuhrzeit>15:35:54</xdomea:Erstellungsuhrzeit>
+      </xdomea:Verfuegung>
+    </xdomea:Beteiligungsschritt>
+  </xdomea:ExternerGeschaeftsgang>
+  <xdomea:Anlage>
+    <xdomea:Dokument>
+      <xdomea:Identifikation>
+        <xdomea:ID>44d72e8a-f8e3-484b-bf0c-a84cf1aebe0c</xdomea:ID>
+      </xdomea:Identifikation>
+      <xdomea:Typ>Anlage</xdomea:Typ>
+      <xdomea:Version>
+        <xdomea:Nummer>1</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>4bb895cc-7b60-4322-81fa-cf928d1a22e5_00TESTPDF.pdf</xdomea:Dateiname>
+          </xdomea:Primaerdokument>
+        </xdomea:Format>
+      </xdomea:Version>
+    </xdomea:Dokument>
+  </xdomea:Anlage>
+</xdomea:Geschaeftsgang.Geschaeftsgang.0201>
\ No newline at end of file
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dd019ef8d904106ab1e5c20cbc0a10ad4fef5a75
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_with_anlage/73927734-c97b-4823-bad1-60401b112a9f_XML-Daten.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" t:form-version="2.022"
+		t:uuid="a1d537b5-79f1-492b-8966-b66d391fe294" t:id="20240517561130590306" t:timestamp="2024-05-17T13:35:13.586Z"
+		t:sender="test.afm.schleswig-holstein.de" t:form="Brauchtumsfeuer NB Anbindung Test"
+		t:form-id="btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb" t:customer="Schleswig-Holstein" t:customer-id="sh"
+		t:client="Schleswig-Holstein" t:client-id="land" t:lang="de-DE">
+	<GebietID>9006880</GebietID>
+	<AnliegenID>9552000</AnliegenID>
+	<GebietBEZEICHNUNG>Scharbeutz</GebietBEZEICHNUNG>
+	<zst_online_dienst>Brauchtumsfeuer:
+		Anmeldung;266889711;https://www.dataport.de/datenschutz/;WEBSERVICE;;;https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas;https://www.dataport.de/impressum/;true
+	</zst_online_dienst>
+	<datenschutz_akzeptiert>true</datenschutz_akzeptiert>
+	<zustaendigestelle>
+		<OrganisationseinheitenID>9795669</OrganisationseinheitenID>
+	</zustaendigestelle>
+	<OrganisationseinheitenBEZEICHNUNG>Dataport-AFM-SH-Entwicklung Kunstbehörde</OrganisationseinheitenBEZEICHNUNG>
+	<zust_kontaktsystemkennung_ln />
+	<zust_kontaktsystemkennung_nb />
+	<zust_kontaktsystemkennung_webservice>https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas
+	</zust_kontaktsystemkennung_webservice>
+	<zust_strasse>Entwicklerweg</zust_strasse>
+	<zust_hausnummer>123</zust_hausnummer>
+	<zust_postleitzahl>24107</zust_postleitzahl>
+	<ortID>9006402</ortID>
+	<zust_ort>Kiel</zust_ort>
+	<zust_telefonnummer>+49 40 42846-4032</zust_telefonnummer>
+	<zust_faxnummer />
+	<zust_emailadresse>noreply@ozg-sh.de</zust_emailadresse>
+	<anzeigender_verantwortlich>true</anzeigender_verantwortlich>
+	<anzeigender_nachname>mit Anhang</anzeigender_nachname>
+	<anzeigender_vorname>Test</anzeigender_vorname>
+	<anzeigender_geburtsdatum>2001-01-01</anzeigender_geburtsdatum>
+	<anzeigender_land_auswahl>in Deutschland</anzeigender_land_auswahl>
+	<anzeigender_strasse>Test</anzeigender_strasse>
+	<anzeigender_hausnummer>1</anzeigender_hausnummer>
+	<anzeigender_postleitzahl>22222</anzeigender_postleitzahl>
+	<anzeigender_ort>Test</anzeigender_ort>
+	<anzeigender_firma />
+	<kontakt_mail>noreply@ozg-sh.de</kontakt_mail>
+	<kontakt_telefon />
+	<kontakt_mobil />
+	<verantwortlicher_mobil>0123456789</verantwortlicher_mobil>
+	<verantwortlicher_mobil2 />
+	<angabe>adresse</angabe>
+	<strasse>Teststr</strasse>
+	<hausnummer>1</hausnummer>
+	<ort>Scharbeutz</ort>
+	<ortsteil />
+	<angaben_extra />
+	<lageplan>
+		<file content-type="application/pdf" description="" id="assistants.85D54E9431CF70430ACBB8DD3E604E83C03B1891"
+				length="185689">00TESTPDF.pdf
+		</file>
+	</lageplan>
+	<feuer_datum>2025-07-08</feuer_datum>
+	<feuer_start>15:00</feuer_start>
+	<feuer_ende>23:00</feuer_ende>
+	<feuer_groesse>1000</feuer_groesse>
+	<feuer_art>Alles
+	</feuer_art>
+	<feuer_gefahrenabwehr />
+	<weitergabe>true</weitergabe>
+	<richtigkeit>true</richtigkeit>
+	<missbrauch>true</missbrauch>
+	<betreff>Anzeige eines Brauchtumsfeuers</betreff>
+	<nachricht>Sehr geehrte/r Angtragssteller/in&lt;br/&gt;&lt;br/&gt;Ihr Antrag wurde an die zuständige Stelle
+		gesendet.&lt;br/&gt; Ihre Vorgangsnummer und zuständige Stelle finden Sie im angehängten Dokument. &lt;br/&gt;Bitte
+		geben Sie diese Vorgangsnummer bei allen Anfragen zu Ihrerm Antrag an.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Mit
+		freundlichen Grüßen&lt;br/&gt;&lt;br/&gt;Ihre zuständige Stelle
+	</nachricht>
+	<mail />
+	<nameid />
+	<rest_response_name>[]</rest_response_name>
+	<mailboxguid />
+	<antragsteller>
+		<pers_anrede />
+		<pers_nachname>mit Anhang</pers_nachname>
+		<pers_vorname>Test</pers_vorname>
+		<pers_geburtsdatum>2001-01-01</pers_geburtsdatum>
+		<sh_strasse>Test</sh_strasse>
+		<sh_hausnummer>1</sh_hausnummer>
+		<sh_plz>22222</sh_plz>
+		<ort>Test</ort>
+		<kont_telefonnummer />
+		<kont_mobilnummer />
+		<kont_email>noreply@ozg-sh.de</kont_email>
+	</antragsteller>
+</myForm>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e66b92187f6db6335ea86ea32f127d78f70cd786
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e_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>0cec5d74-5ac3-4ff3-9a6f-69007ff3f27e</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-05-17T09:21:09.073+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>e8f627fe-b90c-4fc7-ba61-20a43041971b</xdomea:ID>
+      </xdomea:Identifikation>
+      <xdomea:AllgemeineMetadaten>
+        <xdomea:Betreff>Brauchtumsfeuer NB Anbindung Test</xdomea:Betreff>
+        <xdomea:Kennzeichen>20240517335360945504</xdomea:Kennzeichen>
+      </xdomea:AllgemeineMetadaten>
+      <xdomea:Posteingangsdatum>2024-05-17</xdomea:Posteingangsdatum>
+      <xdomea:Typ>btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb</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>758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml</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>3a41cc59-baf4-424d-8c69-a8e7f7470d68_PDF-Antrag.pdf</xdomea:Dateiname>
+          </xdomea:Primaerdokument>
+        </xdomea:Format>
+      </xdomea:Version>
+    </xdomea:Dokument>
+  </xdomea:Hauptobjekt>
+  <xdomea:ExternerGeschaeftsgang>
+    <xdomea:Identifikation>
+      <xdomea:ID>f5966df2-633a-4763-a769-b4250d66df58</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-05-17</xdomea:Erstellungsdatum>
+        <xdomea:Erstellungsuhrzeit>09:21:06</xdomea:Erstellungsuhrzeit>
+      </xdomea:Verfuegung>
+    </xdomea:Beteiligungsschritt>
+  </xdomea:ExternerGeschaeftsgang>
+</xdomea:Geschaeftsgang.Geschaeftsgang.0201>
\ No newline at end of file
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml
new file mode 100644
index 0000000000000000000000000000000000000000..00e2a77f7ffabafbb4abcb2e81c8701a40b460aa
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/brauchtumsfeuer_without_anlage/758ae7f9-9984-43ba-8dda-b81aa3d92f95_XML-Daten.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction" t:form-version="2.022" t:uuid="147839b0-e938-4606-a8bc-104afd83a2b3" t:id="20240517335360945504" t:timestamp="2024-05-17T07:18:56.031Z" t:sender="test.afm.schleswig-holstein.de" t:form="Brauchtumsfeuer NB Anbindung Test" t:form-id="btf_brauchtumsfeuer_sh/btf_brauchtumsfeuer_nb" t:customer="Schleswig-Holstein" t:customer-id="sh" t:client="Schleswig-Holstein" t:client-id="land" t:lang="de-DE"><GebietID>9006880</GebietID><AnliegenID>9552000</AnliegenID><GebietBEZEICHNUNG>Scharbeutz</GebietBEZEICHNUNG><zst_online_dienst>Brauchtumsfeuer: Anmeldung;266889711;https://www.dataport.de/datenschutz/;WEBSERVICE;;;https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas;https://www.dataport.de/impressum/;true</zst_online_dienst><datenschutz_akzeptiert>true</datenschutz_akzeptiert><zustaendigestelle><OrganisationseinheitenID>9795669</OrganisationseinheitenID></zustaendigestelle><OrganisationseinheitenBEZEICHNUNG>Dataport-AFM-SH-Entwicklung Kunstbehörde</OrganisationseinheitenBEZEICHNUNG><zust_kontaktsystemkennung_ln/><zust_kontaktsystemkennung_nb/><zust_kontaktsystemkennung_webservice>https://atlantis.stage.afm.ozg-sh.de/ws/intelliform_formDatas</zust_kontaktsystemkennung_webservice><zust_strasse>Entwicklerweg</zust_strasse><zust_hausnummer>123</zust_hausnummer><zust_postleitzahl>24107</zust_postleitzahl><ortID>9006402</ortID><zust_ort>Kiel</zust_ort><zust_telefonnummer>+49 40 42846-4032</zust_telefonnummer><zust_faxnummer/><zust_emailadresse>noreply@ozg-sh.de</zust_emailadresse><anzeigender_verantwortlich>true</anzeigender_verantwortlich><anzeigender_nachname>OZG-Cloud</anzeigender_nachname><anzeigender_vorname>Test von</anzeigender_vorname><anzeigender_geburtsdatum>2001-01-01</anzeigender_geburtsdatum><anzeigender_land_auswahl>in Deutschland</anzeigender_land_auswahl><anzeigender_strasse>Teststraße</anzeigender_strasse><anzeigender_hausnummer>1</anzeigender_hausnummer><anzeigender_postleitzahl>22222</anzeigender_postleitzahl><anzeigender_ort>Teststadt</anzeigender_ort><anzeigender_firma/><kontakt_mail>noreply@ozg-sh.de</kontakt_mail><kontakt_telefon/><kontakt_mobil/><verantwortlicher_mobil>0123</verantwortlicher_mobil><verantwortlicher_mobil2/><angabe>adresse</angabe><strasse>Test</strasse><hausnummer>1</hausnummer><ort>Scharbeutz</ort><ortsteil/><angaben_extra/><feuer_datum>2024-10-01</feuer_datum><feuer_start>8:00</feuer_start><feuer_ende>12:00</feuer_ende><feuer_groesse>100</feuer_groesse><feuer_art>Holz
+</feuer_art><feuer_gefahrenabwehr/><weitergabe>true</weitergabe><richtigkeit>true</richtigkeit><missbrauch>true</missbrauch><betreff>Anzeige eines Brauchtumsfeuers</betreff><nachricht>Sehr geehrte/r Angtragssteller/in&lt;br/&gt;&lt;br/&gt;Ihr Antrag wurde an die zuständige Stelle gesendet.&lt;br/&gt; Ihre Vorgangsnummer und zuständige Stelle finden Sie im angehängten Dokument. &lt;br/&gt;Bitte geben Sie diese Vorgangsnummer bei allen Anfragen zu Ihrerm Antrag an.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Mit freundlichen Grüßen&lt;br/&gt;&lt;br/&gt;Ihre zuständige Stelle</nachricht><mail/><nameid/><rest_response_name>[]</rest_response_name><mailboxguid/><antragsteller><pers_anrede/><pers_nachname>OZG-Cloud</pers_nachname><pers_vorname>Test von</pers_vorname><pers_geburtsdatum>2001-01-01</pers_geburtsdatum><sh_strasse>Teststraße</sh_strasse><sh_hausnummer>1</sh_hausnummer><sh_plz>22222</sh_plz><ort>Teststadt</ort><kont_telefonnummer/><kont_mobilnummer/><kont_email>noreply@ozg-sh.de</kont_email></antragsteller></myForm>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml
new file mode 100644
index 0000000000000000000000000000000000000000..14aa5016cdef7d7a084f7e7f83b3be12e24d99da
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.dataport.de/dFAD/ApplicationDataMessageSchema">
+  <ApplicationFormId>08dc645c-6704-48e7-868c-6afa8510384c</ApplicationFormId>
+  <Timestamp>2024-04-24T16:32:54.696248+02:00</Timestamp>
+  <ApplicationDataMessageVersion>3</ApplicationDataMessageVersion>
+  <Title>OZG-Cloud Test 2.0</Title>
+  <ProjectName>OZG-Cloud Test 2.0</ProjectName>
+  <ProjectTitle>OZG-Cloud Test 2.0</ProjectTitle>
+  <TransmittedApplicationId>UGLAG4ILLpz6a0</TransmittedApplicationId>
+  <MetaText1>9795669</MetaText1>
+  <InboxReference>hh/hh/4dd01647-b9d9-4775-1b50-08da3d83800a</InboxReference>
+  <AuthenticationAccountType>ServicekontoBasic</AuthenticationAccountType>
+  <AuthenticationMethod>UsernameAndPassword</AuthenticationMethod>
+  <AuthenticationIdentityDetails xsi:nil="true" />
+  <Pages>
+    <Page>
+      <Title>Willkommen auf Ihrer neuen Seite</Title>
+      <Navigation>Freimodul 1</Navigation>
+      <Controls>
+        <Control>
+          <Upload>
+            <Label>Dateiupload</Label>
+            <Alias />
+            <Files>
+              <Name>Admin.png</Name>
+            </Files>
+          </Upload>
+        </Control>
+      </Controls>
+    </Page>
+  </Pages>
+</application>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/b29d45cc-9aac-4452-ad08-60f5ab3bab95_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/b29d45cc-9aac-4452-ad08-60f5ab3bab95_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..021987e3a06b61d8f509507c6cb9cac5ae4c8e44
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_with_anlage/b29d45cc-9aac-4452-ad08-60f5ab3bab95_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,128 @@
+<?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>b29d45cc-9aac-4452-ad08-60f5ab3bab95</ProzessID>
+    <Nachrichtentyp listURI="urn:xoev-de:xdomea:codeliste:nachrichtentyp" listVersionID="1.0">
+      <code xmlns="">0201</code>
+    </Nachrichtentyp>
+    <Erstellungszeitpunkt>2024-04-24T16:32:54.7247984+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>5d142b11-7b52-4bfc-b14d-8d02fee84aa3</ID>
+      </Identifikation>
+      <AllgemeineMetadaten>
+        <Betreff>OZG-Cloud Test 2.0</Betreff>
+        <Kennzeichen>08dc645c-6704-48e7-868c-6afa8510384c</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>3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714_Fachnachricht.xml</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>06d36643-2883-4b74-9231-8dc7f2693af2_Zusammenfassung-01f903b0-c61e-429d-807f-5011d180c073.pdf</Dateiname>
+          </Primaerdokument>
+        </Format>
+      </Version>
+    </Dokument>
+  </Hauptobjekt>
+  <ExternerGeschaeftsgang>
+    <Identifikation>
+      <ID>3ecc7e49-5dc2-499a-9be8-ce8b9d8c8714</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-24</Erstellungsdatum>
+        <Erstellungsuhrzeit>16:32:54</Erstellungsuhrzeit>
+      </Verfuegung>
+    </Beteiligungsschritt>
+  </ExternerGeschaeftsgang>
+  <Anlage>
+    <Dokument>
+      <Identifikation>
+        <ID>1d8ca22a-9d20-4507-aa5e-b764bb5642f0</ID>
+      </Identifikation>
+      <Typ>Anlage</Typ>
+      <Version>
+        <Nummer>1</Nummer>
+        <Format>
+          <Name listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" xsi:type="DateiformatCodeType">
+            <code xmlns="">019</code>
+            <name xmlns="">png-Portable Network Graphics</name>
+          </Name>
+          <Version>0.0</Version>
+          <Primaerdokument>
+            <Dateiname>1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png</Dateiname>
+          </Primaerdokument>
+        </Format>
+      </Version>
+    </Dokument>
+  </Anlage>
+</Geschaeftsgang.Geschaeftsgang.0201>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml
new file mode 100644
index 0000000000000000000000000000000000000000..618c4813e1803a0619c68920505c9ee7cb303b12
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.dataport.de/dFAD/ApplicationDataMessageSchema">
+	<ApplicationFormId>08db3c1c-db1f-4d27-8dec-73af167e87f2</ApplicationFormId>
+	<Timestamp>2023-04-18T11:40:24.9940624+02:00</Timestamp>
+	<ApplicationDataMessageVersion>1</ApplicationDataMessageVersion>
+	<Title>Testantrag XML-Fachnachricht-Erweiterung</Title>
+	<ProjectName>XML-Fachnachricht-Erweiterung</ProjectName>
+	<ProjectTitle>XML-Fachnachricht-Erweiterung</ProjectTitle>
+	<TransmittedApplicationId>7AtSMHpx3LfJp4</TransmittedApplicationId>
+	<InboxReference>sh/sh/4dd01647-b9d9-4775-1b50-08da3d83800a</InboxReference>
+	<MetaText1>9795669</MetaText1>
+	<Pages>
+		<Page>
+			<Title>Beispiel Seite 1</Title>
+			<Navigation>Beispiel Seite 1</Navigation>
+			<Controls>
+				<Control>
+					<RadioButtonGroup>
+						<Label>Beispiel-Steuerelement</Label>
+						<Alias>beispiel-element</Alias>
+						<SelectedItems>
+							<SelectedItem>
+								<Label>Beispielwert 2</Label>
+								<Value>bsp-2</Value>
+							</SelectedItem>
+						</SelectedItems>
+					</RadioButtonGroup>
+				</Control>
+			</Controls>
+		</Page>
+	</Pages>
+</application>
\ No newline at end of file
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7f6df652f0ab5a5338b3e97fc3daff00bcb41a8d
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/dfoerdermittel_without_anlage/d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Geschaeftsgang.Geschaeftsgang.0201 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		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>d5be7468-e620-4126-a40e-61a7f9b46345</ProzessID>
+		<Nachrichtentyp listURI="urn:xoev-de:xdomea:codeliste:nachrichtentyp" listVersionID="1.0">
+			<code xmlns="">0201</code>
+		</Nachrichtentyp>
+		<Erstellungszeitpunkt>2023-04-04T06:59:15.4231885+02:00</Erstellungszeitpunkt>
+		<Absender>
+			<Behoerdenkennung>
+				<Kennung listURI="" listVersionID="">
+					<code xmlns="">010100200000</code>
+				</Kennung>
+				<Praefix listURI="" listVersionID="">
+					<code xmlns="">gad</code>
+				</Praefix>
+			</Behoerdenkennung>
+		</Absender>
+		<Empfaenger>
+			<Behoerdenkennung>
+				<Kennung listURI="" listVersionID="">
+					<code xmlns="">noreply@ozg-sh.de</code>
+				</Kennung>
+				<Praefix listURI="" listVersionID="">
+					<code xmlns="">gae</code>
+				</Praefix>
+			</Behoerdenkennung>
+		</Empfaenger>
+		<SendendesSystem>
+			<InstanzID>DE_dFoerdermittelantrag</InstanzID>
+			<Produktname>dFoerdermittelantrag</Produktname>
+			<Version>1.0.1.0</Version>
+		</SendendesSystem>
+		<EmpfangsbestaetigungAnInitiator>false</EmpfangsbestaetigungAnInitiator>
+		<EmpfangsbestaetigungAnVorgaenger>false</EmpfangsbestaetigungAnVorgaenger>
+	</Kopf>
+	<Hauptobjekt>
+		<Dokument>
+			<Identifikation>
+				<ID>be180ad4-da79-4de2-99b9-86aac2ca7c32</ID>
+			</Identifikation>
+			<AllgemeineMetadaten>
+				<Betreff>OZG-Cloud XTA-Test</Betreff>
+				<Kennzeichen>08db344b-0302-478e-8bc2-37edeb652460</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>269562a3-9142-45b8-9bd2-db840b8322bf_Fachnachricht.xml</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>c2170d27-7a58-4d94-afdf-62c89b9e1557_Zusammenfassung.pdf</Dateiname>
+					</Primaerdokument>
+				</Format>
+			</Version>
+		</Dokument>
+	</Hauptobjekt>
+	<ExternerGeschaeftsgang>
+		<Identifikation>
+			<ID>269562a3-9142-45b8-9bd2-db840b8322bf</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="">010100200000</code>
+						</Kennung>
+						<Praefix listURI="" listVersionID="">
+							<code xmlns="">gad</code>
+						</Praefix>
+					</Behoerdenkennung>
+				</Ersteller>
+				<Adressat>
+					<Behoerdenkennung>
+						<Kennung listURI="" listVersionID="">
+							<code xmlns="">noreply@ozg-sh.de</code>
+						</Kennung>
+						<Praefix listURI="" listVersionID="">
+							<code xmlns="">gae</code>
+						</Praefix>
+					</Behoerdenkennung>
+				</Adressat>
+				<Erstellungsdatum>2023-04-04</Erstellungsdatum>
+				<Erstellungsuhrzeit>06:59:15</Erstellungsuhrzeit>
+			</Verfuegung>
+		</Beteiligungsschritt>
+	</ExternerGeschaeftsgang>
+</Geschaeftsgang.Geschaeftsgang.0201>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0b5280964f200398c1e683ed9622f19ab7c31554
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction"
+		t:uuid="1d4a1b9b-b456-4d76-becb-eff301665993" t:id="20240404370530710707" t:timestamp="2024-04-04T08:17:33.211Z"
+		t:sender="test.afm.schleswig-holstein.de"
+		t:form="Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe"
+		t:form-id="maa_mantelantrag/maa_mantelantrag_pvog" t:customer="Schleswig-Holstein" t:customer-id="sh"
+		t:client="Schleswig-Holstein" t:client-id="land" t:lang="de" t:vollstaendigkeit="true">
+	<gebiets_id>9007404</gebiets_id>
+	<egh_sgb9>true</egh_sgb9>
+	<bes_wohnform>false</bes_wohnform>
+	<hzl>false</hzl>
+	<grusi>false</grusi>
+	<hzg>false</hzg>
+	<hzp>false</hzp>
+	<hzuebss>false</hzuebss>
+	<hial>false</hial>
+	<ambulant>false</ambulant>
+	<stationaer>false</stationaer>
+	<sessionid>4cb66bdd-ad27-41c6-8f4b-fc7f023970ad</sessionid>
+	<anliegen_id>[8969232]</anliegen_id>
+	<anliegen_namen>[Eingliederungshilfe]</anliegen_namen>
+	<TypenIDLN>233034601</TypenIDLN>
+	<logopath1>https://include-sh-schul.zfinder.de/IWFileLoader?tsaid_mediaUUID=21734555-12d6-47aa-bd2e-5794634c592c
+	</logopath1>
+	<logopath2 />
+	<logopath3 />
+	<gebiet_typid>300004</gebiet_typid>
+	<gebiet_parent_id1>9006398</gebiet_parent_id1>
+	<gebiet_parent_typid1>300003</gebiet_parent_typid1>
+	<gebiet_parent_id2>9006398</gebiet_parent_id2>
+	<gebiet_parent_typid2>300003</gebiet_parent_typid2>
+	<gebiet_parent_id3>9006398</gebiet_parent_id3>
+	<gebiet_parent_typid3>300003</gebiet_parent_typid3>
+	<gebiet_parent_name3>Segeberg</gebiet_parent_name3>
+	<oeid>[266237176]</oeid>
+	<link_datenschutz>https://dse.segeberg.de/pdf/50_30_001.pdf</link_datenschutz>
+	<link_datenschutz2 />
+	<link_datenschutz3 />
+	<link_bankgeheimnis>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_Befreiung_vom_Bankgeheimnis.pdf
+	</link_bankgeheimnis>
+	<link_grundsicherung>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Erklaerung_zur_Zahlung_von_Grundsicherungsleistungen_an_Leistungserbringer.pdf
+	</link_grundsicherung>
+	<link_schweigepflicht>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Schweigepflichtentbindung.pdf
+	</link_schweigepflicht>
+	<link_abtretung>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Einverstaendniserklaerung_und_Abtretung.pdf
+	</link_abtretung>
+	<link_wahrheit>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_der_antragstellenden_Person.pdf
+	</link_wahrheit>
+	<kontaktsystem_oeid>9795669</kontaktsystem_oeid>
+	<OrganisationseinheitenBEZEICHNUNG>Kreis Segeberg - Eingliederungshilfe für Minderjährige
+	</OrganisationseinheitenBEZEICHNUNG>
+	<zust_strasse>Hamburger Straße</zust_strasse>
+	<zust_hausnummer>30</zust_hausnummer>
+	<zust_postleitzahl>23795</zust_postleitzahl>
+	<ortid>9007404</ortid>
+	<zust_ort>Bad Segeberg</zust_ort>
+	<zust_telefonnummer />
+	<zust_faxnummer />
+	<zust_emailadresse>Eingliederungshilfe-Minderjaehrige@segeberg.de</zust_emailadresse>
+	<zustellung_nachrichtenbroker>afmsh:010600000000_Online-Dienste</zustellung_nachrichtenbroker>
+	<zustellung_email_ln />
+	<zustellung_webservice />
+	<kontaktsystem_oeid2 />
+	<OrganisationseinheitenBEZEICHNUNG2 />
+	<zust_strasse2 />
+	<zust_hausnummer2 />
+	<zust_postleitzahl2 />
+	<ortid2 />
+	<zust_ort2 />
+	<zust_telefonnummer2 />
+	<zust_faxnummer2 />
+	<zust_emailadresse2 />
+	<zustellung_nachrichtenbroker2 />
+	<zustellung_email_ln2 />
+	<zustellung_webservice2 />
+	<kontaktsystem_oeid3 />
+	<OrganisationseinheitenBEZEICHNUNG3 />
+	<zust_strasse3 />
+	<zust_hausnummer3 />
+	<zust_postleitzahl3 />
+	<ortid3 />
+	<zust_ort3 />
+	<zust_telefonnummer3 />
+	<zust_faxnummer3 />
+	<zust_emailadresse3 />
+	<zustellung_nachrichtenbroker3 />
+	<zustellung_email_ln3 />
+	<zustellung_webservice3 />
+	<grund>Hilfe</grund>
+	<a_grund_bescheinigung>false</a_grund_bescheinigung>
+	<nur_egh>true</nur_egh>
+	<nur_blindenhilfe>false</nur_blindenhilfe>
+	<nur_pers_angaben>false</nur_pers_angaben>
+	<nur_pers_mehrbedarfe>false</nur_pers_mehrbedarfe>
+	<antragsteller>
+		<anrede />
+		<titel />
+		<pers_nachname>Mustermann</pers_nachname>
+		<geburtsname />
+		<pers_vorname>Max</pers_vorname>
+		<geburtsdatum>2000-04-05</geburtsdatum>
+		<geburtsort />
+		<sh_strasse>Musterstrasse</sh_strasse>
+		<sh_hausnummer>12</sh_hausnummer>
+		<adresszusatz />
+		<sh_plz>12345</sh_plz>
+		<ort>Bad Segeberg</ort>
+		<kont_email />
+		<telefon />
+		<mobiltelefon />
+		<familienstand>ledig</familienstand>
+		<deutsch>deutsch</deutsch>
+		<a_ausweisdokument>false</a_ausweisdokument>
+		<erwerb />
+		<erwerbsunfaehig />
+		<betreuer>false</betreuer>
+		<partner>false</partner>
+		<kont_telefonnummer />
+	</antragsteller>
+	<angaben_antragsteller>
+		<sozialhilfe_p>Nein</sozialhilfe_p>
+		<eingliederungshilfe>Nein</eingliederungshilfe>
+		<leistungen>Nein</leistungen>
+		<rentenantrag>Nein</rentenantrag>
+		<sozialversicherungsnummer />
+		<rentenbeitraege />
+		<auslandserwerb />
+		<lebensunterhalt>Arbeit</lebensunterhalt>
+		<zuzug>false</zuzug>
+		<pflege_noetig />
+		<ansprueche_dritte>false</ansprueche_dritte>
+		<stoerung_vorhanden>false</stoerung_vorhanden>
+		<sozialhilfe>Nein</sozialhilfe>
+	</angaben_antragsteller>
+	<weitere_personen>false</weitere_personen>
+	<fin_antragsteller>
+		<groesse_wohnung unit="m2" />
+		<untervermietet_wohnung unit="m2" />
+		<raeume />
+		<baujahr />
+		<wohnung_kosten unit="Euro" />
+		<betriebskosten unit="Euro" />
+		<heizkosten unit="Euro" />
+		<heizart />
+		<a_mietvertrag>false</a_mietvertrag>
+		<pauschalmiete unit="Euro" />
+		<warmwasser />
+		<miete_vermieter />
+		<wohngeld />
+	</fin_antragsteller>
+	<wohnart>Mietwohnung</wohnart>
+	<ver>
+		<ver-item>
+			<name_id>a</name_id>
+			<versicherung_vorhanden>false</versicherung_vorhanden>
+			<name>Max Mustermann</name>
+			<fruehere_kv_vorhanden />
+			<frueherer_erwerb_v />
+			<bedarf_hzg />
+			<kuenftige_kv />
+		</ver-item>
+	</ver>
+	<werkstatt />
+	<leistungen_bezogen>false</leistungen_bezogen>
+	<einkommen_antragsteller>
+		<lgh_hzl_bg />
+		<nselbststaendig_vorhanden>false</nselbststaendig_vorhanden>
+		<gewerbe_vorhanden>false</gewerbe_vorhanden>
+		<landwirtschaft_vorhanden>false</landwirtschaft_vorhanden>
+		<vermietung_vorhanden>false</vermietung_vorhanden>
+		<kapital_vorhanden>false</kapital_vorhanden>
+		<krankenkasse_vorhanden>false</krankenkasse_vorhanden>
+		<pflegekasse_vorhanden>false</pflegekasse_vorhanden>
+		<alg_vorhanden>false</alg_vorhanden>
+		<leistungen_afa_vorhanden>false</leistungen_afa_vorhanden>
+		<wohngeld_vorhanden>false</wohngeld_vorhanden>
+		<kindergeld_vorhanden>false</kindergeld_vorhanden>
+		<elterngeld_vorhanden>false</elterngeld_vorhanden>
+		<rente_inland_vorhanden>false</rente_inland_vorhanden>
+		<rente_ausland_vorhanden>false</rente_ausland_vorhanden>
+		<rente_sonstige_vorhanden>false</rente_sonstige_vorhanden>
+		<unterhalt_vorhanden>false</unterhalt_vorhanden>
+		<blindengeld_vorhanden>false</blindengeld_vorhanden>
+		<sonstiges_vorhanden>false</sonstiges_vorhanden>
+		<einkommen_gepfaendet>false</einkommen_gepfaendet>
+		<einkommen_vorhanden>false</einkommen_vorhanden>
+	</einkommen_antragsteller>
+	<vermoegen>
+		<vermoegen-item>
+			<name_id>a</name_id>
+			<bargeld_vorhanden>false</bargeld_vorhanden>
+			<konto_vorhanden>false</konto_vorhanden>
+			<sparguthaben_vorhanden>false</sparguthaben_vorhanden>
+			<altersvorsorge_vorhanden>false</altersvorsorge_vorhanden>
+			<bausparvertraege_vorhanden>false</bausparvertraege_vorhanden>
+			<aktien_vorhanden>false</aktien_vorhanden>
+			<paypal_vorhanden>false</paypal_vorhanden>
+			<lebensversicherung_vorhanden>false</lebensversicherung_vorhanden>
+			<kfz_vorhanden>false</kfz_vorhanden>
+			<sachwerte_vorhanden>false</sachwerte_vorhanden>
+			<haus_vorhanden>false</haus_vorhanden>
+			<hypotheken_vorhanden>false</hypotheken_vorhanden>
+			<erbschaft_vorhanden>false</erbschaft_vorhanden>
+			<sonstiges_vorhanden>false</sonstiges_vorhanden>
+			<veraeusserung_vermoegen>false</veraeusserung_vermoegen>
+			<vermoegen_vorhanden>false</vermoegen_vorhanden>
+			<name>Max Mustermann</name>
+		</vermoegen-item>
+	</vermoegen>
+	<datenerhebung>true</datenerhebung>
+	<vollstaendigkeit>true</vollstaendigkeit>
+	<a_befreiung_bankgeheimnis>false</a_befreiung_bankgeheimnis>
+	<a_entbindung_schweigepflicht>false</a_entbindung_schweigepflicht>
+	<name_bank />
+	<iban />
+	<kontoinhaber />
+	<name_pdf>Antrag_Max_Mustermann_SGBIX</name_pdf>
+	<postfachnachicht>Sehr geehrte/r Antragsteller*in,&lt;br/&gt;&lt;br/&gt;Ihr Antrag wurde erfolgreich übermittelt.&lt;br/&gt;&lt;br/&gt;Bitte
+		denken Sie daran, zur Vervollständigung Ihres Antrages die unterschriebenen Dokumente und erforderlichen
+		Nachweise einzureichen.&lt;br/&gt;&lt;br/&gt;Die Bearbeitung Ihres Antrages ist erst nach Vorlage aller
+		erforderlichen Dokumente und Nachweise möglich.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Mit freundlichen Grüßen&lt;br/&gt;&lt;br/&gt;Kreis
+		Segeberg - Eingliederungshilfe für Minderjährige&lt;br/&gt;Hamburger Straße 30&lt;br/&gt;23795 Bad Segeberg
+	</postfachnachicht>
+</myForm>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..184ed14cc0f0fccad28c5053ad69f50fe9bcb0d0
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_with_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,110 @@
+<?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>6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml</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>03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf</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:Anlage>
+  <xdomea:Dokument>
+    <xdomea:Identifikation>
+      <xdomea:ID>1d8ca22a-9d20-4507-aa5e-b764bb5642f0</xdomea:ID>
+    </xdomea:Identifikation>
+    <xdomea:Typ>Anlage</xdomea:Typ>
+    <xdomea:Version>
+      <xdomea:Nummer>1</xdomea:Nummer>
+      <xdomea:Format>
+        <xdomea:Name listURI="urn:xoev-de:xdomea:codeliste:dateiformat" listVersionID="1.0" xsi:type="DateiformatCodeType">
+          <xdomea:code xmlns="">019</xdomea:code>
+          <xdomea:name xmlns="">png-Portable Network Graphics</xdomea:name>
+        </xdomea:Name>
+        <xdomea:Version>0.0</xdomea:Version>
+        <xdomea:Primaerdokument>
+          <xdomea:Dateiname>1d8ca22a-9d20-4507-aa5e-b764bb5642f0_Admin.png</xdomea:Dateiname>
+        </xdomea:Primaerdokument>
+      </xdomea:Format>
+    </xdomea:Version>
+  </xdomea:Dokument>
+</xdomea:Anlage>
+</xdomea:Geschaeftsgang.Geschaeftsgang.0201>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0b5280964f200398c1e683ed9622f19ab7c31554
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<myForm xmlns:t="http://xmlns.cit.de/intelliform/transaction"
+		t:uuid="1d4a1b9b-b456-4d76-becb-eff301665993" t:id="20240404370530710707" t:timestamp="2024-04-04T08:17:33.211Z"
+		t:sender="test.afm.schleswig-holstein.de"
+		t:form="Antrag auf Leistungen der Eingliederungshilfe und/oder Sozialhilfe"
+		t:form-id="maa_mantelantrag/maa_mantelantrag_pvog" t:customer="Schleswig-Holstein" t:customer-id="sh"
+		t:client="Schleswig-Holstein" t:client-id="land" t:lang="de" t:vollstaendigkeit="true">
+	<gebiets_id>9007404</gebiets_id>
+	<egh_sgb9>true</egh_sgb9>
+	<bes_wohnform>false</bes_wohnform>
+	<hzl>false</hzl>
+	<grusi>false</grusi>
+	<hzg>false</hzg>
+	<hzp>false</hzp>
+	<hzuebss>false</hzuebss>
+	<hial>false</hial>
+	<ambulant>false</ambulant>
+	<stationaer>false</stationaer>
+	<sessionid>4cb66bdd-ad27-41c6-8f4b-fc7f023970ad</sessionid>
+	<anliegen_id>[8969232]</anliegen_id>
+	<anliegen_namen>[Eingliederungshilfe]</anliegen_namen>
+	<TypenIDLN>233034601</TypenIDLN>
+	<logopath1>https://include-sh-schul.zfinder.de/IWFileLoader?tsaid_mediaUUID=21734555-12d6-47aa-bd2e-5794634c592c
+	</logopath1>
+	<logopath2 />
+	<logopath3 />
+	<gebiet_typid>300004</gebiet_typid>
+	<gebiet_parent_id1>9006398</gebiet_parent_id1>
+	<gebiet_parent_typid1>300003</gebiet_parent_typid1>
+	<gebiet_parent_id2>9006398</gebiet_parent_id2>
+	<gebiet_parent_typid2>300003</gebiet_parent_typid2>
+	<gebiet_parent_id3>9006398</gebiet_parent_id3>
+	<gebiet_parent_typid3>300003</gebiet_parent_typid3>
+	<gebiet_parent_name3>Segeberg</gebiet_parent_name3>
+	<oeid>[266237176]</oeid>
+	<link_datenschutz>https://dse.segeberg.de/pdf/50_30_001.pdf</link_datenschutz>
+	<link_datenschutz2 />
+	<link_datenschutz3 />
+	<link_bankgeheimnis>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_Befreiung_vom_Bankgeheimnis.pdf
+	</link_bankgeheimnis>
+	<link_grundsicherung>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Erklaerung_zur_Zahlung_von_Grundsicherungsleistungen_an_Leistungserbringer.pdf
+	</link_grundsicherung>
+	<link_schweigepflicht>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Schweigepflichtentbindung.pdf
+	</link_schweigepflicht>
+	<link_abtretung>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Anlage_Einverstaendniserklaerung_und_Abtretung.pdf
+	</link_abtretung>
+	<link_wahrheit>
+		https://test.afm.schleswig-holstein.de/intelliform/templates/land/default/default/maa_mantelantrag/Erklaerung_der_antragstellenden_Person.pdf
+	</link_wahrheit>
+	<kontaktsystem_oeid>9795669</kontaktsystem_oeid>
+	<OrganisationseinheitenBEZEICHNUNG>Kreis Segeberg - Eingliederungshilfe für Minderjährige
+	</OrganisationseinheitenBEZEICHNUNG>
+	<zust_strasse>Hamburger Straße</zust_strasse>
+	<zust_hausnummer>30</zust_hausnummer>
+	<zust_postleitzahl>23795</zust_postleitzahl>
+	<ortid>9007404</ortid>
+	<zust_ort>Bad Segeberg</zust_ort>
+	<zust_telefonnummer />
+	<zust_faxnummer />
+	<zust_emailadresse>Eingliederungshilfe-Minderjaehrige@segeberg.de</zust_emailadresse>
+	<zustellung_nachrichtenbroker>afmsh:010600000000_Online-Dienste</zustellung_nachrichtenbroker>
+	<zustellung_email_ln />
+	<zustellung_webservice />
+	<kontaktsystem_oeid2 />
+	<OrganisationseinheitenBEZEICHNUNG2 />
+	<zust_strasse2 />
+	<zust_hausnummer2 />
+	<zust_postleitzahl2 />
+	<ortid2 />
+	<zust_ort2 />
+	<zust_telefonnummer2 />
+	<zust_faxnummer2 />
+	<zust_emailadresse2 />
+	<zustellung_nachrichtenbroker2 />
+	<zustellung_email_ln2 />
+	<zustellung_webservice2 />
+	<kontaktsystem_oeid3 />
+	<OrganisationseinheitenBEZEICHNUNG3 />
+	<zust_strasse3 />
+	<zust_hausnummer3 />
+	<zust_postleitzahl3 />
+	<ortid3 />
+	<zust_ort3 />
+	<zust_telefonnummer3 />
+	<zust_faxnummer3 />
+	<zust_emailadresse3 />
+	<zustellung_nachrichtenbroker3 />
+	<zustellung_email_ln3 />
+	<zustellung_webservice3 />
+	<grund>Hilfe</grund>
+	<a_grund_bescheinigung>false</a_grund_bescheinigung>
+	<nur_egh>true</nur_egh>
+	<nur_blindenhilfe>false</nur_blindenhilfe>
+	<nur_pers_angaben>false</nur_pers_angaben>
+	<nur_pers_mehrbedarfe>false</nur_pers_mehrbedarfe>
+	<antragsteller>
+		<anrede />
+		<titel />
+		<pers_nachname>Mustermann</pers_nachname>
+		<geburtsname />
+		<pers_vorname>Max</pers_vorname>
+		<geburtsdatum>2000-04-05</geburtsdatum>
+		<geburtsort />
+		<sh_strasse>Musterstrasse</sh_strasse>
+		<sh_hausnummer>12</sh_hausnummer>
+		<adresszusatz />
+		<sh_plz>12345</sh_plz>
+		<ort>Bad Segeberg</ort>
+		<kont_email />
+		<telefon />
+		<mobiltelefon />
+		<familienstand>ledig</familienstand>
+		<deutsch>deutsch</deutsch>
+		<a_ausweisdokument>false</a_ausweisdokument>
+		<erwerb />
+		<erwerbsunfaehig />
+		<betreuer>false</betreuer>
+		<partner>false</partner>
+		<kont_telefonnummer />
+	</antragsteller>
+	<angaben_antragsteller>
+		<sozialhilfe_p>Nein</sozialhilfe_p>
+		<eingliederungshilfe>Nein</eingliederungshilfe>
+		<leistungen>Nein</leistungen>
+		<rentenantrag>Nein</rentenantrag>
+		<sozialversicherungsnummer />
+		<rentenbeitraege />
+		<auslandserwerb />
+		<lebensunterhalt>Arbeit</lebensunterhalt>
+		<zuzug>false</zuzug>
+		<pflege_noetig />
+		<ansprueche_dritte>false</ansprueche_dritte>
+		<stoerung_vorhanden>false</stoerung_vorhanden>
+		<sozialhilfe>Nein</sozialhilfe>
+	</angaben_antragsteller>
+	<weitere_personen>false</weitere_personen>
+	<fin_antragsteller>
+		<groesse_wohnung unit="m2" />
+		<untervermietet_wohnung unit="m2" />
+		<raeume />
+		<baujahr />
+		<wohnung_kosten unit="Euro" />
+		<betriebskosten unit="Euro" />
+		<heizkosten unit="Euro" />
+		<heizart />
+		<a_mietvertrag>false</a_mietvertrag>
+		<pauschalmiete unit="Euro" />
+		<warmwasser />
+		<miete_vermieter />
+		<wohngeld />
+	</fin_antragsteller>
+	<wohnart>Mietwohnung</wohnart>
+	<ver>
+		<ver-item>
+			<name_id>a</name_id>
+			<versicherung_vorhanden>false</versicherung_vorhanden>
+			<name>Max Mustermann</name>
+			<fruehere_kv_vorhanden />
+			<frueherer_erwerb_v />
+			<bedarf_hzg />
+			<kuenftige_kv />
+		</ver-item>
+	</ver>
+	<werkstatt />
+	<leistungen_bezogen>false</leistungen_bezogen>
+	<einkommen_antragsteller>
+		<lgh_hzl_bg />
+		<nselbststaendig_vorhanden>false</nselbststaendig_vorhanden>
+		<gewerbe_vorhanden>false</gewerbe_vorhanden>
+		<landwirtschaft_vorhanden>false</landwirtschaft_vorhanden>
+		<vermietung_vorhanden>false</vermietung_vorhanden>
+		<kapital_vorhanden>false</kapital_vorhanden>
+		<krankenkasse_vorhanden>false</krankenkasse_vorhanden>
+		<pflegekasse_vorhanden>false</pflegekasse_vorhanden>
+		<alg_vorhanden>false</alg_vorhanden>
+		<leistungen_afa_vorhanden>false</leistungen_afa_vorhanden>
+		<wohngeld_vorhanden>false</wohngeld_vorhanden>
+		<kindergeld_vorhanden>false</kindergeld_vorhanden>
+		<elterngeld_vorhanden>false</elterngeld_vorhanden>
+		<rente_inland_vorhanden>false</rente_inland_vorhanden>
+		<rente_ausland_vorhanden>false</rente_ausland_vorhanden>
+		<rente_sonstige_vorhanden>false</rente_sonstige_vorhanden>
+		<unterhalt_vorhanden>false</unterhalt_vorhanden>
+		<blindengeld_vorhanden>false</blindengeld_vorhanden>
+		<sonstiges_vorhanden>false</sonstiges_vorhanden>
+		<einkommen_gepfaendet>false</einkommen_gepfaendet>
+		<einkommen_vorhanden>false</einkommen_vorhanden>
+	</einkommen_antragsteller>
+	<vermoegen>
+		<vermoegen-item>
+			<name_id>a</name_id>
+			<bargeld_vorhanden>false</bargeld_vorhanden>
+			<konto_vorhanden>false</konto_vorhanden>
+			<sparguthaben_vorhanden>false</sparguthaben_vorhanden>
+			<altersvorsorge_vorhanden>false</altersvorsorge_vorhanden>
+			<bausparvertraege_vorhanden>false</bausparvertraege_vorhanden>
+			<aktien_vorhanden>false</aktien_vorhanden>
+			<paypal_vorhanden>false</paypal_vorhanden>
+			<lebensversicherung_vorhanden>false</lebensversicherung_vorhanden>
+			<kfz_vorhanden>false</kfz_vorhanden>
+			<sachwerte_vorhanden>false</sachwerte_vorhanden>
+			<haus_vorhanden>false</haus_vorhanden>
+			<hypotheken_vorhanden>false</hypotheken_vorhanden>
+			<erbschaft_vorhanden>false</erbschaft_vorhanden>
+			<sonstiges_vorhanden>false</sonstiges_vorhanden>
+			<veraeusserung_vermoegen>false</veraeusserung_vermoegen>
+			<vermoegen_vorhanden>false</vermoegen_vorhanden>
+			<name>Max Mustermann</name>
+		</vermoegen-item>
+	</vermoegen>
+	<datenerhebung>true</datenerhebung>
+	<vollstaendigkeit>true</vollstaendigkeit>
+	<a_befreiung_bankgeheimnis>false</a_befreiung_bankgeheimnis>
+	<a_entbindung_schweigepflicht>false</a_entbindung_schweigepflicht>
+	<name_bank />
+	<iban />
+	<kontoinhaber />
+	<name_pdf>Antrag_Max_Mustermann_SGBIX</name_pdf>
+	<postfachnachicht>Sehr geehrte/r Antragsteller*in,&lt;br/&gt;&lt;br/&gt;Ihr Antrag wurde erfolgreich übermittelt.&lt;br/&gt;&lt;br/&gt;Bitte
+		denken Sie daran, zur Vervollständigung Ihres Antrages die unterschriebenen Dokumente und erforderlichen
+		Nachweise einzureichen.&lt;br/&gt;&lt;br/&gt;Die Bearbeitung Ihres Antrages ist erst nach Vorlage aller
+		erforderlichen Dokumente und Nachweise möglich.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Mit freundlichen Grüßen&lt;br/&gt;&lt;br/&gt;Kreis
+		Segeberg - Eingliederungshilfe für Minderjährige&lt;br/&gt;Hamburger Straße 30&lt;br/&gt;23795 Bad Segeberg
+	</postfachnachicht>
+</myForm>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b6e401f742a42e72ee7f1f040761df15971eb1f5
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/mantelantrag_without_anlage/9f1b47d4-d6bf-4ec4-b0ff-1e30bee42ef2_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>6082c5f7-61ab-4746-a482-0a400cc0301a_Antrag_Max_Mustermann_SGBIX.xml</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>03d5bd15-2c1a-4c50-809c-0efcb21f610f_Antrag_Max_Mustermann_SGBIX.pdf</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>
\ No newline at end of file
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4dabcc067d040ad07fda5101e4c6527459b5d53d
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<myForm xmlns:pdf="http://xmlns.cit.de/assistants/pdf" xmlns:t="http://xmlns.cit.de/intelliform/transaction" t:uuid="2b1b5768-e9b4-47f6-859e-c197ef4361a3" t:id="20240321325940124004" t:timestamp="2024-03-21T08:03:14.724Z" t:sender="test.afm.schleswig-holstein.de" t:form="Kleiner Waffenschein NB Test" t:form-id="waffen/kleinerWaffenscheinNB" t:customer="Einheitlicher Ansprechpartner" t:customer-id="ea-sh" t:client="Schleswig-Holstein" t:client-id="land" t:lang="de">
+	<KontaktsystemTypA>233034600</KontaktsystemTypA>
+	<KontaktsystemTypB>233034601</KontaktsystemTypB>
+	<AnliegenID>8966671</AnliegenID>
+	<antragsteller>
+		<pers_anrede>Herr$03</pers_anrede>
+		<pers_nachname>Max</pers_nachname>
+		<pers_vorname>Mustermann</pers_vorname>
+		<pers_geburtsname>Mustermann</pers_geburtsname>
+		<pers_geburtsdatum>2000-02-15</pers_geburtsdatum>
+		<pers_geburtsort>Eutin</pers_geburtsort>
+		<pers_geburtsland>deutsch$Deutschland$000</pers_geburtsland>
+		<pers_staatsangehoerigkeit>deutsch$Deutschland$000</pers_staatsangehoerigkeit>
+		<b_anrede>Herr</b_anrede>
+		<b_anrede_schluesselnr>03</b_anrede_schluesselnr>
+		<b_geburtsland>Deutschland</b_geburtsland>
+		<b_geburtsland_signatur>000</b_geburtsland_signatur>
+		<b_staatsangehoerigkeit>deutsch</b_staatsangehoerigkeit>
+		<b_staatsangehoerigkeit_signatur>000</b_staatsangehoerigkeit_signatur>
+		<sh_strasse>Musterstrasse</sh_strasse>
+		<sh_hausnummer>123</sh_hausnummer>
+		<sh_plz>23701</sh_plz>
+		<ort_auswahl>9006885$01055012</ort_auswahl>
+		<ort>Eutin</ort>
+		<GebietID>9006885</GebietID>
+		<GebietBEZEICHNUNG>Eutin</GebietBEZEICHNUNG>
+		<GebietGNR94_GNR>01055012</GebietGNR94_GNR>
+		<staat>000</staat>
+		<iso3166numerisch>276</iso3166numerisch>
+		<kont_telefonnummer />
+		<kont_mobilnummer />
+		<kont_telefaxnummer />
+		<kont_email />
+		<kont_demail />
+		<persoenlicheEignung>
+			<maengelvorhanden>false</maengelvorhanden>
+			<ermittlungsverfahren>false</ermittlungsverfahren>
+			<MitgliedschaftInVerboternerVereinigung>false</MitgliedschaftInVerboternerVereinigung>
+		</persoenlicheEignung>
+	</antragsteller>
+	<GebietID>9006885</GebietID>
+	<zustaendigestelle>
+		<OrganisationseinheitenAuswahl>279550874</OrganisationseinheitenAuswahl>
+		<OrganisationseinheitenID>9795669</OrganisationseinheitenID>
+		<OrganisationseinheitenBEZEICHNUNG>Fachdienst Sicherheit und Ordnung - Kreis Ostholstein</OrganisationseinheitenBEZEICHNUNG>
+		<strasse>Lübecker Straße</strasse>
+		<hausnummer>41</hausnummer>
+		<postleitzahl>23701</postleitzahl>
+		<ortID>9006885</ortID>
+		<ort>Eutin</ort>
+		<telefonnummer>+49 4521 788-0</telefonnummer>
+		<telefaxnummer>+49 4521 788-292</telefaxnummer>
+		<emailadresse>sicherheit@kreis-oh.de</emailadresse>
+		<demailadresse />
+		<kontaktsystem_kennung />
+		<kontaktsystem_kennungzusatz />
+		<AnliegenBEZEICHNUNG>Waffenschein beantragen</AnliegenBEZEICHNUNG>
+		<leikaKEYLIST>99089122001000</leikaKEYLIST>
+		<auswahl_zustellung>abholen</auswahl_zustellung>
+		<b_zustellung>Ich hole den Kleinen Waffenschein selbst ab.</b_zustellung>
+	</zustaendigestelle>
+	<empfangendestelle>
+		<OrganisationseinheitenAuswahl>9068873</OrganisationseinheitenAuswahl>
+		<OrganisationseinheitenID>9068873</OrganisationseinheitenID>
+		<OrganisationseinheitenBEZEICHNUNG>Einheitlicher Ansprechpartner Schleswig-Holstein</OrganisationseinheitenBEZEICHNUNG>
+		<strasse>Deliusstraße</strasse>
+		<hausnummer>10</hausnummer>
+		<postleitzahl>24114</postleitzahl>
+		<ortID>9006402</ortID>
+		<ort>Kiel</ort>
+		<telefonnummer>+49 431 530550-0</telefonnummer>
+		<telefaxnummer>+49 431 530550-99</telefaxnummer>
+		<emailadresse>info@ea-sh.de</emailadresse>
+		<demailadresse>ea-poststelle@ea-sh.de-mail.de</demailadresse>
+		<kontaktsystem_kennung>afmsh:9068873_AusnahmeLKWFahrverbot</kontaktsystem_kennung>
+		<kontaktsystem_kennungzusatz>alle</kontaktsystem_kennungzusatz>
+	</empfangendestelle>
+	<erklaerungen>
+		<check_gebuehren>true</check_gebuehren>
+		<check_richtigkeit>true</check_richtigkeit>
+		<check_datenschutz>true</check_datenschutz>
+		<check_missbrauch>true</check_missbrauch>
+		<b_gebuehren_beschriftung>* Mir ist bekannt, dass durch das Einreichen des elektronischen Antrages von der zuständigen Stelle Gebühren erhoben werden können.</b_gebuehren_beschriftung>
+		<b_gebuehren_intro>Gebühr bei Ausstellung des kleinen Waffenscheins: 60,00 Euro. Bearbeitungsgebühr bei Versagung: 45,00 Euro.
+			Sie sind gemäß § 39 WaffG verpflichtet, der zuständigen Behörde die zur Durchführung des Gesetzes erforderlichen Auskünfte zu erteilen. Zur Prüfung Ihrer waffenrechtlichen Zuverlässigkeit und Eignung holt die Behörde eine unbeschränkte Auskunft aus dem Bundeszentralregister, eine Auskunft aus dem zentralen staatsanwaltschaftlichen Verfahrensregister, eine Stellungnahme der örtlichen Polizeidienststelle und Ihrer Wohnsitzgemeinde ein.</b_gebuehren_intro>
+		<b_richtigkeit>* Ich bestätige die Richtigkeit meiner Angaben.</b_richtigkeit>
+		<b_datenschutz>* Ich erkläre mich damit einverstanden, dass der Einheitlicher Ansprechpartner Schleswig-Holstein zur Erfüllung seiner Aufgaben meine Daten unter Einhaltung der Bestimmungen der Datenschutz-Grundverordnung (DS-GVO) und des Landesdatenschutzgesetzes Schleswig-Holstein (LDSG-SH) speichert, verarbeitet und diese im Rahmen der gesetzlichen Bestimmungen an die für die Entscheidung zuständige Stelle weiterleitet. Ebenso bin ich mit der rechtskonformen Datenverarbeitung und Speicherung durch die zuständige Stelle einverstanden. Mir ist bekannt, dass ich die Einwilligung in die Verarbeitung und Übermittlung jederzeit gegenüber dem Einheitlicher Ansprechpartner Schleswig-Holstein, Deliusstraße 10, 24114 Kiel widerrufen kann. Ein Widerruf ist aber nur wirksam für die Zukunft. Verarbeitungen, die vor dem Widerruf erfolgt sind, sind davon nicht betroffen. Über die Verarbeitung meiner personenbezogenen Daten und die mir nach den datenschutzrechtlichen Regelungen zustehenden Ansprüche und Rechte habe ich unter Datenschutzerklärung Kenntnis erlangt.</b_datenschutz>
+		<b_missbrauch>* Mir ist bekannt, dass zur Verfolgung widerrechtlicher Nutzung die Daten meines zur Dateneingabe genutzten Endgerätes aufgezeichnet und verwendet werden können.</b_missbrauch>
+		<policyurl>http://www.ea-sh.info/datenschutz/datenschutzerklaerungEA_de.doc</policyurl>
+	</erklaerungen>
+	<logourl>http://www.ea-sh.info/logos/kopf_9068873.doc</logourl>
+	<fm>
+		<ansprechpartner>
+			<firmenname />
+			<anrede>Herr</anrede>
+			<vorname>Mustermann</vorname>
+			<familienname>Max</familienname>
+			<anschrift>
+				<strasse>Musterstrasse</strasse>
+				<hausnummer>123</hausnummer>
+				<postfach />
+				<postleitzahl>23701</postleitzahl>
+				<ort>Eutin</ort>
+				<ortsteil />
+				<zusatz />
+				<staat>Deutschland</staat>
+			</anschrift>
+			<kontakt>
+				<telefonnummer />
+				<mobilnummer />
+				<telefaxnummer />
+				<emailadresse />
+				<demailadresse />
+			</kontakt>
+		</ansprechpartner>
+		<verwaltungsleistungen>
+			<verwaltungsleistung>
+				<ausgewaehlte_zustaendigestelle>
+					<OrganisationseinheitenID>279550874</OrganisationseinheitenID>
+					<OrganisationseinheitenBEZEICHNUNG>Fachdienst Sicherheit und Ordnung - Kreis Ostholstein</OrganisationseinheitenBEZEICHNUNG>
+				</ausgewaehlte_zustaendigestelle>
+				<GebietID>9006885</GebietID>
+				<GebietBEZEICHNUNG>Eutin</GebietBEZEICHNUNG>
+				<AnliegenID>8966671</AnliegenID>
+				<AnliegenBEZEICHNUNG>Waffenschein beantragen</AnliegenBEZEICHNUNG>
+				<leikaKEYLIST>99089122001000</leikaKEYLIST>
+				<leikaBEZEICHNUNG />
+			</verwaltungsleistung>
+		</verwaltungsleistungen>
+	</fm>
+</myForm>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/d254806f-abf4-4e4c-ae74-ea03460f34d2_Geschaeftsgang.Geschaeftsgang.0201.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/d254806f-abf4-4e4c-ae74-ea03460f34d2_Geschaeftsgang.Geschaeftsgang.0201.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1eaa092e8b3c7f63a6cdf276f3ef763a1302274d
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/Geschaeftsgang.Geschaeftsgang.0201/waffenschein/d254806f-abf4-4e4c-ae74-ea03460f34d2_Geschaeftsgang.Geschaeftsgang.0201.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<xdomea:Geschaeftsgang.Geschaeftsgang.0201 xmlns:xdomea="http://www.xdomea.de/V2.0.1">
+  <xdomea:Kopf>
+    <xdomea:ProzessID>d254806f-abf4-4e4c-ae74-ea03460f34d2</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-03-21T09:05:01.424+01: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>Einheitlicher Ansprechpartner</xdomea:Name>
+        <xdomea:Kurzbezeichnung>Einheitlicher Ansprechpartner</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>5b4e3f41-180b-4a9f-aa5b-19f9aa72f32e</xdomea:ID>
+      </xdomea:Identifikation>
+      <xdomea:AllgemeineMetadaten>
+        <xdomea:Betreff>Kleiner Waffenschein NB Test</xdomea:Betreff>
+        <xdomea:Kennzeichen>20240321325940124004</xdomea:Kennzeichen>
+      </xdomea:AllgemeineMetadaten>
+      <xdomea:Posteingangsdatum>2024-03-21</xdomea:Posteingangsdatum>
+      <xdomea:Typ>waffen/kleinerWaffenscheinNB</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>8248e115-4aec-4253-bb2c-9788823ff9b1_XML-Daten.xml</xdomea:Dateiname>
+          </xdomea:Primaerdokument>
+        </xdomea:Format>
+      </xdomea:Version>
+    </xdomea:Dokument>
+  </xdomea:Hauptobjekt>
+  <xdomea:ExternerGeschaeftsgang>
+    <xdomea:Identifikation>
+      <xdomea:ID>1f6e0806-f9eb-4bb3-88ad-0828411f1f2c</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-03-21</xdomea:Erstellungsdatum>
+        <xdomea:Erstellungsuhrzeit>09:05:01</xdomea:Erstellungsuhrzeit>
+      </xdomea:Verfuegung>
+    </xdomea:Beteiligungsschritt>
+  </xdomea:ExternerGeschaeftsgang>
+</xdomea:Geschaeftsgang.Geschaeftsgang.0201>
diff --git a/xta-adapter/src/test/resources/mock-responses/getMessage/fim.S17000652.17000652001004/versammlungsanzeige.xml b/xta-adapter/src/test/resources/mock-responses/getMessage/fim.S17000652.17000652001004/versammlungsanzeige.xml
new file mode 100644
index 0000000000000000000000000000000000000000..09c2733737951f336ac139a6838df3be550c8a39
--- /dev/null
+++ b/xta-adapter/src/test/resources/mock-responses/getMessage/fim.S17000652.17000652001004/versammlungsanzeige.xml
@@ -0,0 +1 @@
+<fim.S17000652.17000652001004 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:xoev-de:xfall:standard:fim-s17000652_1.4"><G17003529><G05001479><G05001480><F05002750>85ad506f-25a2-4a93-a086-b069784c6d60</F05002750><F05002751>21.03.2024 08:56:33</F05002751><F05002752>fim.S17000652.17000652001004</F05002752><F05002753>urn:fim:Versammlungsanzeige:1.4</F05002753></G05001480><G05001481><F05002754>Fachdienst Sicherheit und Ordnung - Kreis Ostholstein</F05002754><F05002755>vbe:010550120100</F05002755><F05002756>Versammlungsbehörde</F05002756></G05001481><G05001482><F05002754>Dataport</F05002754><F05002755>ehp:010100100000</F05002755><F05002756>Versammlungsbehörde</F05002756></G05001482></G05001479><F17005454>true</F17005454><F17005455>false</F17005455><F17005533>85ad506f-25a2-4a93-a086-b069784c6d60</F17005533></G17003529><F17009191>false</F17009191><G17002112><F60000228>OZG-Cloud</F60000228><F60000227>Team</F60000227><G60000086><F60000243>Muster</F60000243><F60000244>1</F60000244><F60000246>12345</F60000246><F60000247>Muster</F60000247></G60000086><F60000242>noreply@ozg-sh.de</F60000242><F17009011>false</F17009011></G17002112><F17003371>Anzeigen einer ortsfesten Versammlung (Kundgebung / Demonstration)</F17003371><G17005404><G17007202><F17003373>fsdf</F17003373><F17003377>sdf</F17003377><G17005406><F60000048>2024-03-21</F60000048><F17001348>13.5</F17001348><F60000049>2024-03-21</F60000049><F17001349>15</F17001349></G17005406></G17007202><G17007205><F17003379>10</F17003379><F17003382>keine</F17003382><G17007234><F17011826>Nein</F17011826></G17007234><G17007235><F17011827>Nein</F17011827></G17007235></G17007205></G17005404></fim.S17000652.17000652001004>
\ No newline at end of file
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/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>