diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java
index c47e51a4d16204d0e660a16d8f93df57b612655c..0b397f09a56a215d62e51ad804ea1f54d0bb91fd 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java
@@ -231,7 +231,7 @@ class WiedervorlageCommandITCase {
 			@DisplayName("for 41 character in Betreff")
 			@Test
 			void createCommandWithLongBetreff() throws Exception {
-				var content = buildContentWithBetreff(RandomStringUtils.random(41));
+				var content = buildContentWithBetreff(RandomStringUtils.randomAlphanumeric(41));
 
 				doRequest(content).andExpect(status().isUnprocessableEntity());
 			}
diff --git a/alfa-xdomea/pom.xml b/alfa-xdomea/pom.xml
index 8f5d2c08a3647c90e5905617eed3eee3778e4a3a..d4d2b5b35dfad832f17fc795dc7cc62b9ef7b249 100644
--- a/alfa-xdomea/pom.xml
+++ b/alfa-xdomea/pom.xml
@@ -93,7 +93,7 @@
 				</executions>
 				<configuration>
 					<sources>
-						<source>src/main/resources/xdomea_3-0-0_XML-Schemata</source>
+						<source>src/main/resources/ozgcloud_XML-Schemata</source>
 					</sources>
 					<packageName>de.xoev.xdomea</packageName>
 				</configuration>
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/DateConverter.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/DateConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..d475428b3c32af5c4eb4c906de6ed74944072015
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/DateConverter.java
@@ -0,0 +1,49 @@
+package de.ozgcloud.alfa.common;
+
+import java.time.LocalDate;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.Optional;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+public class DateConverter {
+
+	private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMAN);
+
+	public Optional<XMLGregorianCalendar> convertGermanFormatToISO(String dateStr) {
+		try {
+			return Optional.of(createDatatypeFactory().newXMLGregorianCalendar(LocalDate.parse(dateStr, DATE_TIME_FORMATTER).toString()));
+		} catch (Exception e) {
+			LOG.error("Date '{}' cannot be converted to ISO format.", dateStr, e);
+			return Optional.empty();
+		}
+	}
+
+	public XMLGregorianCalendar toXmlGregorianCalendar(ZonedDateTime date) {
+		try {
+			return createDatatypeFactory().newXMLGregorianCalendar(GregorianCalendar.from(date));
+		} catch (Exception e) {
+			throw new TechnicalException("Date '%s' cannot be converted to ISO format.".formatted(date), e);
+		}
+	}
+
+	DatatypeFactory createDatatypeFactory() {
+		try {
+			return DatatypeFactory.newInstance();
+		} catch (DatatypeConfigurationException e) {
+			throw new TechnicalException("Error creating datatype factory.", e);
+		}
+	}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DatentypCode.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/DatentypCode.java
similarity index 71%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DatentypCode.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/DatentypCode.java
index 82eecdff1e5a8834e07165ee8486e8c81589eabf..3ba6ce26689cb4351cfadb74573181ff22d73846 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DatentypCode.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/DatentypCode.java
@@ -1,6 +1,6 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.common;
 
-enum DatentypCode {
+public enum DatentypCode {
 	STRING("038"), DATE("005");
 
 	private String code;
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFilenameGenerator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/ExportFilenameGenerator.java
similarity index 84%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFilenameGenerator.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/ExportFilenameGenerator.java
index 13471e6d59b8ffd385aad5532c1c9bd982172c04..498d74d5aeb964da5e994d149075503aa181ff1c 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFilenameGenerator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/ExportFilenameGenerator.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.common;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -6,7 +6,7 @@ import org.springframework.stereotype.Component;
 import de.ozgcloud.alfa.common.file.OzgFile;
 
 @Component
-class ExportFilenameGenerator {
+public class ExportFilenameGenerator {
 
 	@Autowired
 	private UUIDConverter uuidConverter;
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/UUIDConverter.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/UUIDConverter.java
similarity index 92%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/UUIDConverter.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/UUIDConverter.java
index ad28c0ea96923a9567330fed9fa1bea30cc3f15c..0261329e9b724af6c396ace0a453f57fc7288042 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/UUIDConverter.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/common/UUIDConverter.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.common;
 
 import java.util.regex.Pattern;
 
@@ -6,7 +6,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
 @Component
-class UUIDConverter {
+public class UUIDConverter {
 
 	private static final Pattern UUID_SPLIT_PATTERN = Pattern.compile(
 			"^([a-fA-F0-9]{8})([a-fA-F0-9]{4})([a-fA-F0-9]{4})([a-fA-F0-9]{4})([a-fA-F0-9]+)$");
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeAbgabe0401Creator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeAbgabe0401Creator.java
deleted file mode 100644
index 5cd4aff65c9effe27e31907215043143e2123e5b..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeAbgabe0401Creator.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.xoev.xdomea.AbgabeAbgabe0401;
-
-@Component
-class AbgabeAbgabe0401Creator {
-
-	@Autowired
-	private SchriftgutobjektCreator schriftgutobjektCreator;
-
-	@Autowired
-	private AnwendungsspezifischeErweiterungTypeCreator anwendungsspezifischeErweiterungTypeCreator;
-
-	public AbgabeAbgabe0401 create(VorgangWithEingang vorgang) {
-		var erweiterung = anwendungsspezifischeErweiterungTypeCreator.create(vorgang);
-
-		var abgabe = new AbgabeAbgabe0401();
-		abgabe.getSchriftgutobjekt().add(schriftgutobjektCreator.create(vorgang, erweiterung));
-		return abgabe;
-	}
-
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java
new file mode 100644
index 0000000000000000000000000000000000000000..94914c9bb45b167dd4d4577b0522566f62495c1f
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java
@@ -0,0 +1,55 @@
+package de.ozgcloud.alfa.export;
+
+import java.util.stream.Stream;
+
+import de.xoev.xdomea.AbgabeAbgabe0401;
+import de.xoev.xdomea.DokumentType;
+import de.xoev.xdomea.NkAbgabeType;
+import de.xoev.xdomea.VorgangType;
+
+class AbgabeCreator {
+
+	private AbgabeAbgabe0401 abgabeType;
+
+	private AbgabeCreator() {
+		abgabeType = new AbgabeAbgabe0401();
+	}
+
+	public AbgabeCreator withKopf(NkAbgabeType kopfType) {
+		abgabeType.setKopf(kopfType);
+		return this;
+	}
+
+	public AbgabeCreator withVorgang(VorgangType vorgangType) {
+		getSchriftgutobjekt().setVorgang(vorgangType);
+		return this;
+	}
+
+	public AbgabeCreator withDokumentTypes(Stream<DokumentType> dokumentTypes) {
+		var vorgang = getVorgang();
+		if (vorgang == null) {
+			throw new IllegalStateException("Cannot set documentTypes because Vorgang is null");
+		}
+		dokumentTypes.forEach(vorgang.getDokument()::add);
+		return this;
+	}
+
+	public AbgabeAbgabe0401 create() {
+		return abgabeType;
+	}
+
+	private AbgabeAbgabe0401.Schriftgutobjekt getSchriftgutobjekt() {
+		if (abgabeType.getSchriftgutobjekt().isEmpty()) {
+			abgabeType.getSchriftgutobjekt().add(new AbgabeAbgabe0401.Schriftgutobjekt());
+		}
+		return abgabeType.getSchriftgutobjekt().get(0);
+	}
+
+	private VorgangType getVorgang() {
+		return getSchriftgutobjekt().getVorgang();
+	}
+
+	static AbgabeCreator createAbgabeCreator() {
+		return new AbgabeCreator();
+	}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DateConverter.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DateConverter.java
deleted file mode 100644
index f564300eb2b28c507f84ed17fd789fcb1e08b485..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DateConverter.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.Locale;
-import java.util.Optional;
-
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.common.errorhandling.TechnicalException;
-
-@Component
-class DateConverter {
-
-	private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMAN);
-
-	public Optional<XMLGregorianCalendar> convertGermanFormatToISO(String dateStr) {
-		try {
-			return Optional.of(DatatypeFactory.newInstance().newXMLGregorianCalendar(LocalDate.parse(dateStr, DATE_TIME_FORMATTER).toString()));
-		} catch (DatatypeConfigurationException e) {
-			throw new TechnicalException(String.format("Error converting date %s to ISO.", dateStr), e);
-		} catch (Exception e) {
-			return Optional.empty();
-		}
-	}
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DokumentTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DokumentTypeCreator.java
deleted file mode 100644
index a44e9a8383bdf6088410d5131356b11d739230f2..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DokumentTypeCreator.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.vorgang.Eingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.xoev.xdomea.AllgemeineMetadatenType;
-import de.xoev.xdomea.DokumentType;
-import de.xoev.xdomea.IdentifikationObjektType;
-import de.xoev.xdomea.MediumCodeType;
-
-@Component
-class DokumentTypeCreator {
-
-	static final String ALLGEMEINE_METADATEN_MEDIUM_CODE = "001";
-
-	@Autowired
-	private ExportFileService exportFileService;
-
-	@Autowired
-	private UUIDConverter uuidConverter;
-
-	@Autowired
-	private VersionTypeCreator versionTypeCreator;
-
-	public Stream<DokumentType> create(VorgangWithEingang vorgang) {
-		var ozgFiles = Optional.ofNullable(vorgang.getEingang()).map(Eingang::getId).map(exportFileService::getAllPdfs).map(Stream::toList)
-				.orElse(Collections.emptyList());
-		List<DokumentType> dokumenten = new ArrayList<>(ozgFiles.size());
-		for (var i = 0; i < ozgFiles.size(); i++) {
-			dokumenten.add(createDokumentType(i + 1, vorgang, ozgFiles.get(i)));
-		}
-		return dokumenten.stream();
-	}
-
-	DokumentType createDokumentType(int dokumentOrdinalNumber, VorgangWithEingang vorgang, OzgFile ozgFile) {
-		var dokument = new DokumentType();
-		dokument.setIdentifikation(createIdentifikation(dokumentOrdinalNumber, ozgFile.getId().toString()));
-		dokument.setAllgemeineMetadaten(createAllgemeineMetadaten(ozgFile));
-		dokument.getVersion().add(versionTypeCreator.create(vorgang, ozgFile));
-		return dokument;
-	}
-
-	IdentifikationObjektType createIdentifikation(int dokumentOrdinalNumber, String fileId) {
-		var identifikation = new IdentifikationObjektType();
-		identifikation.setID(uuidConverter.fromObjectId(fileId));
-		identifikation.setNummerImUebergeordnetenContainer(Long.valueOf(dokumentOrdinalNumber));
-		return identifikation;
-	}
-
-	AllgemeineMetadatenType createAllgemeineMetadaten(OzgFile ozgFile) {
-		var allgemeineMetadaten = new AllgemeineMetadatenType();
-		allgemeineMetadaten.setBetreff(ozgFile.getName());
-		allgemeineMetadaten.setKennzeichen(StringUtils.EMPTY);
-		allgemeineMetadaten.setBemerkung(StringUtils.EMPTY);
-		allgemeineMetadaten.setMedium(createMediumCode());
-		return allgemeineMetadaten;
-	}
-
-	private MediumCodeType createMediumCode() {
-		var mediumCode = new MediumCodeType();
-		mediumCode.setCode(ALLGEMEINE_METADATEN_MEDIUM_CODE);
-		return mediumCode;
-	}
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaXmlMarshallerConfiguration.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java
similarity index 93%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaXmlMarshallerConfiguration.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java
index b6b8bd1a0dd4ae9d91e6a8442cb1dc9828da3e4f..a31bf073b13e5293927f8c708e974215baafe495 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaXmlMarshallerConfiguration.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java
@@ -3,15 +3,15 @@ package de.ozgcloud.alfa.export;
 import java.util.HashMap;
 import java.util.Map;
 
-import jakarta.xml.bind.Marshaller;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.oxm.jaxb.Jaxb2Marshaller;
 
+import jakarta.xml.bind.Marshaller;
+
 @Configuration
-class XDomeaXmlMarshallerConfiguration {
+class ExportConfiguration {
 
 	static final boolean JAXB_FORMATTED_OUTPUT = true;
 	static final String PROPERTY_NAMESPACE_PREFIX_MAPPER = "org.glassfish.jaxb.namespacePrefixMapper";
@@ -21,7 +21,7 @@ class XDomeaXmlMarshallerConfiguration {
 	private XDomeaNamespacePrefixMapper prefixMapper;
 
 	@Bean
-	public Jaxb2Marshaller marshaller() {
+	Jaxb2Marshaller marshaller() {
 		var marshaller = new Jaxb2Marshaller();
 		marshaller.setContextPaths(CONTEXT_PATH);
 		marshaller.setMarshallerProperties(createMarshallerProperties());
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportData.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportData.java
index c6e4888c0865072a025a6cf2ecf2729c408dd078..1d23b29d2200e28b0b6863243b31721ca8345db4 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportData.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportData.java
@@ -3,7 +3,7 @@ package de.ozgcloud.alfa.export;
 import java.util.stream.Stream;
 
 import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
+import de.xoev.xdomea.AbgabeAbgabe0401;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -14,9 +14,8 @@ import lombok.Getter;
 @Getter
 class ExportData {
 
-	private VorgangWithEingang vorgang;
 	private String exportFilename;
-	private String xmlFileContent;
+	private AbgabeAbgabe0401 abgabe;
 	private Stream<OzgFile> exportFiles;
 
 }
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaService.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java
similarity index 61%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaService.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java
index d4189560d61dfe343829813da309e35efc3f866c..416cf6fdd698d31657fd1eac79fbf046caa7e9e5 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaService.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java
@@ -13,30 +13,28 @@ import java.util.zip.ZipOutputStream;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import de.ozgcloud.alfa.common.ExportFilenameGenerator;
 import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.vorgang.VorgangController;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
+import de.ozgcloud.alfa.file.ExportFileService;
+import de.ozgcloud.alfa.vorgang.ExportVorgangService;
 import de.ozgcloud.common.binaryfile.TempFileUtils;
 import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.xoev.xdomea.AbgabeAbgabe0401;
 
 @Service
-class XDomeaService {
+class ExportService {
 
 	static final String EXPORT_FILENAME_SUFFIX = "_Abgabe.Abgabe.0401.xml";
-
 	private static final String EXPORT_FILENAME_TEMPLATE = "%s" + EXPORT_FILENAME_SUFFIX;
 
 	@Autowired
 	private XDomeaXmlMarshaller xDomeaXmlMarshaller;
 
 	@Autowired
-	private VorgangController vorgangController;
-
-	@Autowired
-	private AbgabeAbgabe0401Creator abgabeCreator;
+	private ExportFileService exportFileService;
 
 	@Autowired
-	private ExportFileService exportFileService;
+	private ExportVorgangService exportVorgangService;
 
 	@Autowired
 	private ExportFilenameGenerator exportFilenameGenerator;
@@ -48,25 +46,28 @@ class XDomeaService {
 	}
 
 	ExportData collectExportData(String vorgangId, String filenameId) {
-		var vorgang = vorgangController.getVorgang(vorgangId);
-		var xmlContent = createXmlContent(vorgang);
-		var filename = buildXmlFilename(filenameId);
-		var ozgFiles = exportFileService.getAllPdfs(vorgang.getEingang().getId());
-		return ExportData.builder().vorgang(vorgang).xmlFileContent(xmlContent).exportFilename(filename).exportFiles(ozgFiles).build();
+		var vorgangWithEingang = exportVorgangService.getVorgang(vorgangId);
+		var ozgFiles = exportFileService.getAllPdfs(vorgangWithEingang.getEingang().getId());
+		var abgabe = AbgabeCreator.createAbgabeCreator()
+				.withKopf(exportVorgangService.createKopf(vorgangWithEingang))
+				.withVorgang(exportVorgangService.createVorgangType(vorgangWithEingang))
+				.withDokumentTypes(exportFileService.createDokumentTypes(ozgFiles, vorgangWithEingang.getEingang().getHeader().getFormEngineName()))
+				.create();
+		return ExportData.builder().abgabe(abgabe).exportFilename(buildXmlFilename(filenameId)).exportFiles(ozgFiles).build();
 	}
 
 	String buildXmlFilename(String filenameId) {
 		return String.format(EXPORT_FILENAME_TEMPLATE, filenameId);
 	}
 
-	String createXmlContent(VorgangWithEingang vorgang) {
-		return xDomeaXmlMarshaller.marshal(abgabeCreator.create(vorgang));
+	String createXmlContent(AbgabeAbgabe0401 abgabe) {
+		return xDomeaXmlMarshaller.marshal(abgabe);
 	}
 
 	File createZipFile(ExportData exportData) {
 		var file = TempFileUtils.createTmpFile().toFile();
 		try (var zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) {
-			putZipEntry(exportData.getExportFilename(), exportData.getXmlFileContent(), zipOutputStream);
+			putZipEntry(exportData.getExportFilename(), createXmlContent(exportData.getAbgabe()), zipOutputStream);
 			putFilesIntoZip(exportData.getExportFiles(), zipOutputStream);
 			return file;
 		} catch (Exception e) {
@@ -81,17 +82,19 @@ class XDomeaService {
 		zipOutputStream.closeEntry();
 	}
 
-	private void putFilesIntoZip(Stream<OzgFile> ozgFiles, ZipOutputStream zipOutputStream) throws IOException {
-		for (var ozgFile : ozgFiles.toList()) {
-			putOzgFileIntoZip(ozgFile, zipOutputStream);
-		}
+	private void putFilesIntoZip(Stream<OzgFile> ozgFiles, ZipOutputStream zipOutputStream) {
+		ozgFiles.forEach(ozgFile -> putOzgFileIntoZip(ozgFile, zipOutputStream));
 	}
 
-	void putOzgFileIntoZip(OzgFile ozgFile, ZipOutputStream zipOutputStream) throws IOException {
-		var entry = new ZipEntry(exportFilenameGenerator.generateExportFilename(ozgFile));
-		zipOutputStream.putNextEntry(entry);
-		exportFileService.writeOzgFile(ozgFile.getId(), zipOutputStream);
-		zipOutputStream.closeEntry();
+	void putOzgFileIntoZip(OzgFile ozgFile, ZipOutputStream zipOutputStream) {
+		try {
+			var entry = new ZipEntry(exportFilenameGenerator.generateExportFilename(ozgFile));
+			zipOutputStream.putNextEntry(entry);
+			exportFileService.writeOzgFile(ozgFile.getId(), zipOutputStream);
+			zipOutputStream.closeEntry();
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
 	}
 
 	void writeZipFileContent(File file, OutputStream outputStream) {
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangController.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangController.java
index 3dd4f41c18e893d5a573df29ad19e6397a015337..8dc8154f42b755de40f1c9b7addf1316e6dc15db 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangController.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangController.java
@@ -21,7 +21,7 @@ public class ExportVorgangController {
 	private static final String EXPORT_FILENAME_TEMPLATE = "%s_Abgabe.Abgabe.0401.xdomea";
 
 	@Autowired
-	private XDomeaService xDomeaService;
+	private ExportService xDomeaService;
 
 	@GetMapping(value = "{vorgangId}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
 	public ResponseEntity<StreamingResponseBody> exportToXdomea(@PathVariable String vorgangId) {
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/FormatTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/FormatTypeCreator.java
deleted file mode 100644
index c3d9deb3c1f34c36abc1824ab918ac8b12260d4e..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/FormatTypeCreator.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.xoev.xdomea.FormatType;
-
-@Component
-class FormatTypeCreator {
-
-	@Autowired
-	private PrimaerdokumentTypeCreator primaerdokumentTypeCreator;
-
-	public FormatType create(VorgangWithEingang vorgang, OzgFile ozgFile) {
-		var format = new FormatType();
-		format.setPrimaerdokument(primaerdokumentTypeCreator.create(vorgang, ozgFile));
-		format.setName(DateiformatCode.PDF.createDateiformatCodeType());
-		format.setSonstigerName(StringUtils.EMPTY);
-		format.setVersion(StringUtils.EMPTY);
-		return format;
-	}
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeCreator.java
deleted file mode 100644
index 593e0ef8195aed2d85c3d8290317e80f5efadf5c..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeCreator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.xoev.xdomea.PrimaerdokumentType;
-
-@Component
-class PrimaerdokumentTypeCreator {
-
-	@Autowired
-	private ExportFilenameGenerator exportFilenameGenerator;
-
-	public PrimaerdokumentType create(VorgangWithEingang vorgang, OzgFile ozgFile) {
-		var primaerdokument = new PrimaerdokumentType();
-		primaerdokument.setDateiname(exportFilenameGenerator.generateExportFilename(ozgFile));
-		primaerdokument.setDateinameOriginal(ozgFile.getName());
-		primaerdokument.setErsteller(vorgang.getEingang().getHeader().getFormEngineName());
-		return primaerdokument;
-	}
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/SchriftgutobjektCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/SchriftgutobjektCreator.java
deleted file mode 100644
index 2ba904f2ceb9027f3d14d96736d0219242361b3f..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/SchriftgutobjektCreator.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.xoev.xdomea.AbgabeAbgabe0401.Schriftgutobjekt;
-import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
-
-@Component
-class SchriftgutobjektCreator {
-
-	@Autowired
-	private VorgangTypeCreator vorgangTypeCreator;
-
-	public Schriftgutobjekt create(VorgangWithEingang vorgang, AnwendungsspezifischeErweiterungType erweiterung) {
-		var schritftgutobjekt = new Schriftgutobjekt();
-		schritftgutobjekt.setVorgang(vorgangTypeCreator.create(vorgang, erweiterung));
-		return schritftgutobjekt;
-	}
-
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/VersionTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/VersionTypeCreator.java
deleted file mode 100644
index 7ce323a415aa2181efcd27795de794d256f61b41..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/VersionTypeCreator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.xoev.xdomea.VersionType;
-
-@Component
-class VersionTypeCreator {
-
-	static final String NUMMER = "1";
-
-	@Autowired
-	private FormatTypeCreator formatTypeCreator;
-
-	public VersionType create(VorgangWithEingang vorgang, OzgFile ozgFile) {
-		var version = new VersionType();
-		version.setNummer(NUMMER);
-		version.getFormat().add(formatTypeCreator.create(vorgang, ozgFile));
-		return version;
-	}
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaProperties.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa2898bed501872596eca02a1d45a3c822fc256a
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XDomeaProperties.java
@@ -0,0 +1,19 @@
+package de.ozgcloud.alfa.export;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Configuration
+@ConfigurationProperties("ozgcloud.xdomea")
+public class XDomeaProperties {
+
+	/**
+	 * XDomea Behoerdenschluessel.
+	 */
+	private String behoerdenschluessel;
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DateiformatCode.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/DateiformatCode.java
similarity index 94%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DateiformatCode.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/DateiformatCode.java
index c7f4b8f86717fb9646e9a32f8b1b28318297c278..5042e73ea5b7578281de666e1e1e2c92e532cf70 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DateiformatCode.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/DateiformatCode.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import de.xoev.xdomea.DateiformatCodeType;
 
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/DokumentTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/DokumentTypeCreator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f86626bb5f5c4499c9d813b01686c0f50f7c17ce
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/DokumentTypeCreator.java
@@ -0,0 +1,100 @@
+package de.ozgcloud.alfa.file;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.alfa.common.ExportFilenameGenerator;
+import de.ozgcloud.alfa.common.UUIDConverter;
+import de.ozgcloud.alfa.common.file.OzgFile;
+import de.xoev.xdomea.AllgemeineMetadatenType;
+import de.xoev.xdomea.DokumentType;
+import de.xoev.xdomea.FormatType;
+import de.xoev.xdomea.IdentifikationObjektType;
+import de.xoev.xdomea.MediumCodeType;
+import de.xoev.xdomea.PrimaerdokumentType;
+import de.xoev.xdomea.VersionType;
+
+@Component
+class DokumentTypeCreator {
+
+	static final String VERSION_NUMMER = "1";
+	static final String ALLGEMEINE_METADATEN_MEDIUM_CODE = "001";
+
+	@Autowired
+	private UUIDConverter uuidConverter;
+
+	@Autowired
+	private ExportFilenameGenerator exportFilenameGenerator;
+
+	public Stream<DokumentType> create(Stream<OzgFile> ozgFiles, String formEngineName) {
+		final var ordinalNumberGenerator = new AtomicInteger(1);
+		return ozgFiles.map(ozgFile -> createDokumentType(new MappingData(ozgFile, ordinalNumberGenerator.getAndIncrement(), formEngineName)));
+	}
+
+	DokumentType createDokumentType(MappingData mappingData) {
+		var dokumentType = new DokumentType();
+		dokumentType.setIdentifikation(createIdentifikation(mappingData));
+		dokumentType.setAllgemeineMetadaten(createAllgemeineMetadaten(mappingData));
+
+		var versionType = createVersionType();
+		dokumentType.getVersion().add(versionType);
+
+		var formatType = createFormatType();
+		versionType.getFormat().add(formatType);
+
+		var primaerdokumentType = createPrimaerdokumentType(mappingData);
+		formatType.setPrimaerdokument(primaerdokumentType);
+
+		return dokumentType;
+	}
+
+	IdentifikationObjektType createIdentifikation(MappingData mappingData) {
+		var identifikation = new IdentifikationObjektType();
+		identifikation.setID(uuidConverter.fromObjectId(mappingData.ozgFile().getId().toString()));
+		identifikation.setNummerImUebergeordnetenContainer(Long.valueOf(mappingData.dokumentOrdinalNumber()));
+		return identifikation;
+	}
+
+	AllgemeineMetadatenType createAllgemeineMetadaten(MappingData mappingData) {
+		var allgemeineMetadaten = new AllgemeineMetadatenType();
+		allgemeineMetadaten.setBetreff(mappingData.ozgFile().getName());
+		allgemeineMetadaten.setKennzeichen(StringUtils.EMPTY);
+		allgemeineMetadaten.setBemerkung(StringUtils.EMPTY);
+		allgemeineMetadaten.setMedium(createMediumCode());
+		return allgemeineMetadaten;
+	}
+
+	private MediumCodeType createMediumCode() {
+		var mediumCode = new MediumCodeType();
+		mediumCode.setCode(ALLGEMEINE_METADATEN_MEDIUM_CODE);
+		return mediumCode;
+	}
+
+	private VersionType createVersionType() {
+		var versionType = new VersionType();
+		versionType.setNummer(VERSION_NUMMER);
+		return versionType;
+	}
+
+	private FormatType createFormatType() {
+		var formatType = new FormatType();
+		formatType.setName(DateiformatCode.PDF.createDateiformatCodeType());
+		formatType.setSonstigerName(StringUtils.EMPTY);
+		formatType.setVersion(StringUtils.EMPTY);
+		return formatType;
+	}
+
+	private PrimaerdokumentType createPrimaerdokumentType(MappingData mappingData) {
+		var primaerdokumentType = new PrimaerdokumentType();
+		primaerdokumentType.setDateiname(exportFilenameGenerator.generateExportFilename(mappingData.ozgFile()));
+		primaerdokumentType.setDateinameOriginal(mappingData.ozgFile().getName());
+		primaerdokumentType.setErsteller(mappingData.formEngineName());
+		return primaerdokumentType;
+	}
+
+	record MappingData (OzgFile ozgFile, int dokumentOrdinalNumber, String formEngineName) {}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFileService.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/ExportFileService.java
similarity index 76%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFileService.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/ExportFileService.java
index 31a4a322a44b9b086bd3cc29b27e4746e99446c5..c224b6c04fdb5fda786fca7dea4bf3f65a08edab 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFileService.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/file/ExportFileService.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import java.io.OutputStream;
 import java.util.function.Predicate;
@@ -12,9 +12,10 @@ import de.ozgcloud.alfa.common.binaryfile.BinaryFileService;
 import de.ozgcloud.alfa.common.binaryfile.FileId;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileService;
+import de.xoev.xdomea.DokumentType;
 
 @Service
-class ExportFileService {
+public class ExportFileService {
 
 	private static final Predicate<OzgFile> IS_PDF_FILE = file -> file.getContentType().equals(MediaType.APPLICATION_PDF_VALUE);
 
@@ -24,12 +25,19 @@ class ExportFileService {
 	@Autowired
 	private BinaryFileService binaryFileService;
 
+	@Autowired
+	private DokumentTypeCreator dokumentTypeCreator;
+
 	public Stream<OzgFile> getAllPdfs(String eingangId) {
 		var representations = ozgFileService.getRepresentationsByEingang(eingangId);
 		var attachments = ozgFileService.getAttachmentsByEingang(eingangId);
 		return Stream.concat(representations, attachments).filter(IS_PDF_FILE);
 	}
 
+	public Stream<DokumentType> createDokumentTypes(Stream<OzgFile> ozgFileStream, String formEngineName) {
+		return dokumentTypeCreator.create(ozgFileStream, formEngineName);
+	}
+
 	public void writeOzgFile(FileId fileId, OutputStream outputStream) {
 		binaryFileService.writeFileContent(fileId, outputStream);
 	}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeCreator.java
similarity index 51%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeCreator.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeCreator.java
index d981a15c7542d2ba1e5a46c4094d43bb8e7b9223..0e98a75fee4b6339c8a5db5d74aaddfc043a7017 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeCreator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeCreator.java
@@ -1,12 +1,12 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import java.util.Collections;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
 import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
+import de.xoev.xdomea.OzgcloudErweiterungType;
 
 @Component
 class AnwendungsspezifischeErweiterungTypeCreator {
@@ -16,12 +16,16 @@ class AnwendungsspezifischeErweiterungTypeCreator {
 
 	@Autowired
 	private FeldGruppeTypeCreator feldGruppeTypeCreator;
+	@Autowired
+	private FormDataMapper formDataMapper;
 
 	public AnwendungsspezifischeErweiterungType create(VorgangWithEingang vorgang) {
-		var anwendungsspezifischeErweiterung = new AnwendungsspezifischeErweiterungType();
-		anwendungsspezifischeErweiterung.setKennung(KENNUNG);
-		anwendungsspezifischeErweiterung.setName(NAME);
-		anwendungsspezifischeErweiterung.getFeldgruppe().addAll(Collections.singleton(feldGruppeTypeCreator.create(vorgang)));
-		return anwendungsspezifischeErweiterung;
+		var ozgcloudErweiterungType = new OzgcloudErweiterungType();
+		ozgcloudErweiterungType.setKennung(KENNUNG);
+		ozgcloudErweiterungType.setName(NAME);
+		ozgcloudErweiterungType.getFeldgruppe().addAll(Collections.singleton(feldGruppeTypeCreator.create(vorgang)));
+		ozgcloudErweiterungType.setAntragsdaten(formDataMapper.toAntragsdatenType(vorgang));
+		return ozgcloudErweiterungType;
 	}
+
 }
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/DatatypeMapper.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/DatatypeMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a740682a45f0793f2926172b98212060617c603
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/DatatypeMapper.java
@@ -0,0 +1,44 @@
+package de.ozgcloud.alfa.vorgang;
+
+import static java.util.Objects.*;
+
+import java.time.LocalDate;
+import java.time.ZonedDateTime;
+import java.util.Collection;
+
+import org.springframework.stereotype.Component;
+
+import de.xoev.xdomea.DatatypeType;
+
+@Component
+class DatatypeMapper {
+
+	public DatatypeType from(Object object) {
+		if (isNull(object)) {
+			return DatatypeType.STRING;
+		}
+		var objectClass = object.getClass();
+		if (String.class.equals(objectClass)) {
+			return DatatypeType.STRING;
+		}
+		if (Integer.class.equals(objectClass)) {
+			return DatatypeType.INTEGER;
+		}
+		if (Boolean.class.equals(objectClass)) {
+			return DatatypeType.BOOLEAN;
+		}
+		if (LocalDate.class.equals(objectClass)) {
+			return DatatypeType.DATE;
+		}
+		if (ZonedDateTime.class.equals(objectClass)) {
+			return DatatypeType.DATETIME;
+		}
+		if (Float.class.equals(objectClass)) {
+			return DatatypeType.FLOAT;
+		}
+		if (object instanceof Collection<?> collection && !collection.isEmpty()) {
+			return from(collection.iterator().next());
+		}
+		return DatatypeType.STRING;
+	}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFelder.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportFelder.java
similarity index 95%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFelder.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportFelder.java
index bcb17930abf6e9b98135975e6ad09ea6ac602c9c..46db0e389e308eba98b8a9e9664306c1c972016b 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportFelder.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportFelder.java
@@ -1,5 +1,6 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
+import de.ozgcloud.alfa.common.DatentypCode;
 import de.xoev.xdomea.DatentypCodeType;
 import de.xoev.xdomea.FeldType;
 
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9065991f2beabac2478595cdfb3dafab372f6fd
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java
@@ -0,0 +1,32 @@
+package de.ozgcloud.alfa.vorgang;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.xoev.xdomea.NkAbgabeType;
+import de.xoev.xdomea.VorgangType;
+
+@Service
+public class ExportVorgangService {
+
+	@Autowired
+	private VorgangService vorgangService;
+
+	@Autowired
+	private VorgangTypeCreator vorgangTypeCreator;
+
+	@Autowired
+	private KopfCreator kopfCreator;
+
+	public VorgangWithEingang getVorgang(String vorgangId) {
+		return vorgangService.findVorgangWithEingang(vorgangId);
+	}
+
+	public VorgangType createVorgangType(VorgangWithEingang vorgangWithEingang) {
+		return vorgangTypeCreator.create(vorgangWithEingang);
+	}
+
+	public NkAbgabeType createKopf(VorgangWithEingang vorgangWithEingang) {
+		return kopfCreator.createKopf(vorgangWithEingang);
+	}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/FeldGruppeTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FeldGruppeTypeCreator.java
similarity index 94%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/FeldGruppeTypeCreator.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FeldGruppeTypeCreator.java
index e47cc16c6db59f270bade24eb4389ab91190ba0e..6b22705890f313c97caae1fad6692ea7405dd208 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/FeldGruppeTypeCreator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FeldGruppeTypeCreator.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static java.util.Optional.*;
 
@@ -8,7 +8,6 @@ import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
 import de.xoev.xdomea.FeldType;
 import de.xoev.xdomea.FeldgruppeType;
 
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2aba0f9fde6b7f2ae5d0c515ba95d70e3cf6d78
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java
@@ -0,0 +1,93 @@
+package de.ozgcloud.alfa.vorgang;
+
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import jakarta.validation.constraints.NotNull;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.alfa.common.DateConverter;
+import de.xoev.xdomea.AntragsdatenGroupType;
+import de.xoev.xdomea.AntragsdatenItemType;
+import de.xoev.xdomea.AntragsdatenMultiValueFieldType;
+import de.xoev.xdomea.AntragsdatenSingleValueFieldType;
+import de.xoev.xdomea.AntragsdatenType;
+import de.xoev.xdomea.DatatypeType;
+import de.xoev.xdomea.ItemListType;
+
+@Component
+class FormDataMapper {
+
+	@Autowired
+	private DatatypeMapper datatypeMapper;
+	@Autowired
+	private DateConverter dateConverter;
+
+	public AntragsdatenType toAntragsdatenType(@NotNull VorgangWithEingang vorgang) {
+		return Optional.ofNullable(vorgang.getEingang()).map(Eingang::getFormData).map(this::buileItemListType).map(AntragsdatenType.class::cast)
+				.orElseGet(AntragsdatenType::new);
+	}
+
+	ItemListType buileItemListType(Map<?, ?> formData) {
+		var itemList = new AntragsdatenType();
+		itemList.getItem().addAll(buildItems(formData));
+		return itemList;
+	}
+
+	List<AntragsdatenItemType> buildItems(Map<?, ?> formData) {
+		var items = new ArrayList<AntragsdatenItemType>();
+		for (var formDataEntry : formData.entrySet()) {
+			var key = (String) formDataEntry.getKey();
+			var value = formDataEntry.getValue();
+			if (value instanceof Map<?, ?> map) {
+				items.add(buildAntragsdatenGroup(key, map));
+			} else if (value instanceof Collection<?> collection) {
+				items.add(buildMultiValueField(key, collection));
+			} else {
+				items.add(buildSingleValueField(key, value));
+
+			}
+		}
+		return items;
+	}
+
+	AntragsdatenItemType buildAntragsdatenGroup(String name, Map<?, ?> values) {
+		var antragsGroup = new AntragsdatenGroupType();
+		antragsGroup.setName(name);
+		antragsGroup.setValue(buileItemListType(values));
+		return antragsGroup;
+	}
+
+	AntragsdatenItemType buildMultiValueField(String name, Collection<?> values) {
+		var multiValue = new AntragsdatenMultiValueFieldType();
+		multiValue.setName(name);
+		var datatype = datatypeMapper.from(values);
+		multiValue.setType(datatype);
+		var multiValueList = multiValue.getValue();
+		values.stream().map(v -> formatValue(datatype, v)).forEach(multiValueList::add);
+		return multiValue;
+	}
+
+	AntragsdatenItemType buildSingleValueField(String name, Object value) {
+		var singleValue = new AntragsdatenSingleValueFieldType();
+		singleValue.setName(name);
+		var datatype = datatypeMapper.from(value);
+		singleValue.setType(datatype);
+		singleValue.setValue(formatValue(datatype, value));
+		return singleValue;
+	}
+
+	Object formatValue(DatatypeType datatype, Object value) {
+		return switch (datatype) {
+			case STRING -> String.valueOf(value);
+			case DATETIME -> dateConverter.toXmlGregorianCalendar((ZonedDateTime) value);
+			default -> value;
+		};
+	}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/KontaktTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KontaktTypeCreator.java
similarity index 71%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/KontaktTypeCreator.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KontaktTypeCreator.java
index 0f13079a7a8acba8763844ca936ee785c27ba62e..8521f74b3b600a85b4e19c85813c0caebb7f011f 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/KontaktTypeCreator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KontaktTypeCreator.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import java.util.Optional;
 import java.util.function.Predicate;
@@ -9,18 +9,16 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.alfa.vorgang.Antragsteller;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
+import de.ozgcloud.alfa.common.DateConverter;
 import de.xoev.xdomea.GeburtType;
 import de.xoev.xdomea.KontaktType;
 
 @Component
 class KontaktTypeCreator {
 
-	private final Predicate<Antragsteller> HAS_VORNAME = antragsteller -> StringUtils.isNotBlank(antragsteller.getVorname());
-	private final Predicate<Antragsteller> HAS_NACHNAME = antragsteller -> StringUtils.isNotBlank(antragsteller.getNachname());
-	private final Predicate<Antragsteller> HAS_ANREDE = antragsteller -> StringUtils.isNotBlank(antragsteller.getAnrede());
-	private final Predicate<Antragsteller> HAS_VALID_GEBURTSDATUM = this::hasValidGeburtsdatum;
+	private static final Predicate<Antragsteller> HAS_VORNAME = antragsteller -> StringUtils.isNotBlank(antragsteller.getVorname());
+	private static final Predicate<Antragsteller> HAS_NACHNAME = antragsteller -> StringUtils.isNotBlank(antragsteller.getNachname());
+	private static final Predicate<Antragsteller> HAS_ANREDE = antragsteller -> StringUtils.isNotBlank(antragsteller.getAnrede());
 
 	@Autowired
 	private NameNatuerlichePersonTypeCreator nameNatuerlichePersonTypeCreator;
@@ -34,7 +32,7 @@ class KontaktTypeCreator {
 
 	Optional<Antragsteller> getAntragstellerIfHasRequiredData(VorgangWithEingang vorgang) {
 		return Optional.ofNullable(vorgang.getEingang().getAntragsteller())
-				.filter(HAS_VORNAME.or(HAS_NACHNAME).or(HAS_ANREDE).or(HAS_VALID_GEBURTSDATUM));
+				.filter(HAS_VORNAME.or(HAS_NACHNAME).or(HAS_ANREDE).or(this::hasValidGeburtsdatum));
 	}
 
 	KontaktType toKontaktType(Antragsteller antragsteller) {
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ca24c46586dd757ea0b258476e5c6d36119c200
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java
@@ -0,0 +1,94 @@
+package de.ozgcloud.alfa.vorgang;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.alfa.common.DateConverter;
+import de.ozgcloud.alfa.export.XDomeaProperties;
+import de.xoev.xdomea.BehoerdenkennungType;
+import de.xoev.xdomea.Code;
+import de.xoev.xdomea.KontaktType;
+import de.xoev.xdomea.NachrichtentypCodeType;
+import de.xoev.xdomea.NkAbgabeType;
+import de.xoev.xdomea.OrganisationseinheitType;
+import de.xoev.xdomea.SystemType;
+
+@Component
+class KopfCreator {
+
+	static final String BEHOERDENSCHLUSSEL_LIST_URI = "urn:de:bund:destatis:bevoelkerungsstatistik:schluessel:rs";
+	static final String BEHOERDENSCHLUSSEL_LIST_VERSION_ID = "2023-11-30";
+
+	static final String NACHRICHTENTYP_CODE_TYPE_LIST_URI = "urn:xoev-de:xdomea:codeliste:nachrichtentyp";
+	static final String NACHRICHTENTYP_CODE_TYPE_LIST_VERSION_ID = "2.0";
+	static final String NACHRICHTENTYP_ABGABE_ABGABE_TYPE_CODE = "0401";
+	static final String PRODUKT_NAME = "OZG-Cloud";
+
+	@Autowired
+	private XDomeaProperties xDomeaProperties;
+	@Autowired
+	private DateConverter dateConverter;
+
+	public NkAbgabeType createKopf(VorgangWithEingang vorgang) {
+		var nkAbgabeType = new NkAbgabeType();
+		nkAbgabeType.setProzessID(vorgang.getId());
+		nkAbgabeType.setNachrichtentyp(createNachrichtentyp());
+		nkAbgabeType.setErstellungszeitpunkt(dateConverter.toXmlGregorianCalendar(ZonedDateTime.now(ZoneOffset.UTC)));
+		nkAbgabeType.setAbsender(createAbsender(vorgang.getEingang().getZustaendigeStelle().getOrganisationseinheitenId()));
+		nkAbgabeType.setEmpfaenger(createKontaktType());
+		nkAbgabeType.setSendendesSystem(creeateSendendesSystem());
+		nkAbgabeType.setImportbestaetigung(true);
+		nkAbgabeType.setEmpfangsbestaetigung(true);
+		return nkAbgabeType;
+	}
+
+	NachrichtentypCodeType createNachrichtentyp() {
+		var nachrichtentypCode = new NachrichtentypCodeType();
+		nachrichtentypCode.setCode(NACHRICHTENTYP_ABGABE_ABGABE_TYPE_CODE);
+		nachrichtentypCode.setListURI(NACHRICHTENTYP_CODE_TYPE_LIST_URI);
+		nachrichtentypCode.setListVersionID(NACHRICHTENTYP_CODE_TYPE_LIST_VERSION_ID);
+		return nachrichtentypCode;
+	}
+
+	KontaktType createAbsender(String organisationseinheitId) {
+		var absender = createKontaktType();
+		absender.setOrganisationseinheit(createOrganisationseinheitType(organisationseinheitId));
+		return absender;
+	}
+
+	KontaktType createKontaktType() {
+		var kontakt = new KontaktType();
+		kontakt.setBehoerdenkennung(createBehoerdenkennung());
+		return kontakt;
+	}
+
+	OrganisationseinheitType createOrganisationseinheitType(String organisationseinheitId) {
+		var organisationseinheit = new OrganisationseinheitType();
+		organisationseinheit.setName(organisationseinheitId);
+		return organisationseinheit;
+	}
+
+	BehoerdenkennungType createBehoerdenkennung() {
+		var behoerdenkennungType = new BehoerdenkennungType();
+		behoerdenkennungType.setBehoerdenschluessel(createBehoerdenschlussen());
+		return behoerdenkennungType;
+	}
+
+	Code createBehoerdenschlussen() {
+		var behoerdenschlussel = new Code();
+		behoerdenschlussel.setCode(xDomeaProperties.getBehoerdenschluessel());
+		behoerdenschlussel.setListURI(BEHOERDENSCHLUSSEL_LIST_URI);
+		behoerdenschlussel.setListVersionID(BEHOERDENSCHLUSSEL_LIST_VERSION_ID);
+		return behoerdenschlussel;
+	}
+
+	SystemType creeateSendendesSystem() {
+		var sendendesSystem = new SystemType();
+		sendendesSystem.setProduktname(PRODUKT_NAME);
+		return sendendesSystem;
+	}
+
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeCreator.java
similarity index 92%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeCreator.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeCreator.java
index 285854614408573b9f9238c000e7943ed94800e9..3f4431f47450482dd6c2543460f19219f3d1d5c5 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeCreator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeCreator.java
@@ -1,11 +1,10 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static java.util.Optional.*;
 
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.alfa.vorgang.Antragsteller;
 import de.xoev.xdomea.AllgemeinerNameType;
 import de.xoev.xdomea.NameNatuerlichePersonType;
 
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/VorgangTypeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreator.java
similarity index 81%
rename from alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/VorgangTypeCreator.java
rename to alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreator.java
index 792143b96e0074e5ffdbcd1c48a204759d8d710e..407cf0e979cee700cace3e23fde329ebdbf4136c 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/VorgangTypeCreator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreator.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import java.util.UUID;
 
@@ -6,9 +6,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
 import de.xoev.xdomea.AllgemeineMetadatenType;
-import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
 import de.xoev.xdomea.IdentifikationObjektType;
 import de.xoev.xdomea.MediumCodeType;
 import de.xoev.xdomea.VorgangType;
@@ -20,17 +18,16 @@ class VorgangTypeCreator {
 	static final String ALLGEMEINE_METADATEN_MEDIUM_CODE = "001";
 
 	@Autowired
-	private DokumentTypeCreator dokumentTypeCreator;
+	private AnwendungsspezifischeErweiterungTypeCreator anwendungsspezifischeErweiterungTypeCreator;
 
 	@Autowired
 	private KontaktTypeCreator kontaktTypeCreator;
 
-	public VorgangType create(VorgangWithEingang vorgangWithEingang, AnwendungsspezifischeErweiterungType erweiterung) {
+	public VorgangType create(VorgangWithEingang vorgangWithEingang) {
 		var vorgang = new VorgangType();
-		vorgang.setAnwendungsspezifischeErweiterung(erweiterung);
+		vorgang.setAnwendungsspezifischeErweiterung(anwendungsspezifischeErweiterungTypeCreator.create(vorgangWithEingang));
 		vorgang.setIdentifikation(createIdentifikation());
 		vorgang.setAllgemeineMetadaten(createAllgemeineMetadaten(vorgangWithEingang));
-		vorgang.getDokument().addAll(dokumentTypeCreator.create(vorgangWithEingang).toList());
 		kontaktTypeCreator.create(vorgangWithEingang).ifPresent(vorgang.getKontakt()::add);
 		return vorgang;
 	}
diff --git a/alfa-xdomea/src/main/resources/ozgcloud_XML-Schemata/ozgcloud.xsd b/alfa-xdomea/src/main/resources/ozgcloud_XML-Schemata/ozgcloud.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..fd20e4462893778c836d38217d2b9d78e1724aa5
--- /dev/null
+++ b/alfa-xdomea/src/main/resources/ozgcloud_XML-Schemata/ozgcloud.xsd
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="urn:ozgcloud-de:xdomea:schema:1.0.0"
+		   xmlns:ozgcloud="urn:ozgcloud-de:xdomea:schema:1.0.0"
+		   xmlns:xs="http://www.w3.org/2001/XMLSchema"
+		   xmlns:xdomea="urn:xoev-de:xdomea:schema:3.0.0"
+		   elementFormDefault="qualified">
+
+	<xs:import namespace="urn:xoev-de:xdomea:schema:3.0.0" schemaLocation="../xdomea_3-0-0_XML-Schemata/xdomea.xsd"/>
+
+	<xs:complexType name="OzgcloudErweiterungType">
+		<xs:complexContent>
+			<xs:extension base="xdomea:AnwendungsspezifischeErweiterungType">
+				<xs:sequence>
+					<xs:element name="Antragsdaten" type="ozgcloud:AntragsdatenType"/>
+				</xs:sequence>
+			</xs:extension>
+		</xs:complexContent>
+	</xs:complexType>
+
+	<xs:complexType name="AntragsdatenType">
+		<xs:complexContent>
+			<xs:extension base="ozgcloud:ItemListType"/>
+		</xs:complexContent>
+	</xs:complexType>
+
+	<xs:complexType name="AntragsdatenItemType" abstract="true">
+		<xs:attribute name="name" type="xs:string" use="required"/>
+	</xs:complexType>
+
+	<xs:complexType name="AntragsdatenFieldType" abstract="true">
+		<xs:complexContent>
+			<xs:extension base="ozgcloud:AntragsdatenItemType">
+				<xs:attribute name="type" type="ozgcloud:DatatypeType" default="string"/>
+			</xs:extension>
+		</xs:complexContent>
+	</xs:complexType>
+
+	<xs:complexType name="AntragsdatenSingleValueFieldType">
+		<xs:complexContent>
+			<xs:extension base="ozgcloud:AntragsdatenFieldType">
+				<xs:all>
+					<xs:element name="Value" type="xs:anyType"/>
+				</xs:all>
+			</xs:extension>
+		</xs:complexContent>
+	</xs:complexType>
+
+	<xs:complexType name="AntragsdatenMultiValueFieldType">
+		<xs:complexContent>
+			<xs:extension base="ozgcloud:AntragsdatenFieldType">
+				<xs:sequence>
+					<xs:element name="Value" type="xs:anyType" maxOccurs="unbounded"/>
+				</xs:sequence>
+			</xs:extension>
+		</xs:complexContent>
+	</xs:complexType>
+
+	<xs:complexType name="AntragsdatenGroupType">
+		<xs:complexContent>
+			<xs:extension base="ozgcloud:AntragsdatenItemType">
+				<xs:sequence>
+					<xs:element name="Value" type="ozgcloud:ItemListType"/>
+				</xs:sequence>
+			</xs:extension>
+		</xs:complexContent>
+	</xs:complexType>
+
+	<xs:complexType name="ItemListType" abstract="true">
+		<xs:sequence>
+			<xs:element name="Item" type="ozgcloud:AntragsdatenItemType" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+
+	<xs:simpleType name="DatatypeType">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="string"/>
+			<xs:enumeration value="date"/>
+			<xs:enumeration value="datetime"/>
+			<xs:enumeration value="integer"/>
+			<xs:enumeration value="float"/>
+			<xs:enumeration value="boolean"/>
+		</xs:restriction>
+	</xs:simpleType>
+</xs:schema>
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DateConverterTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/common/DateConverterTest.java
similarity index 74%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DateConverterTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/common/DateConverterTest.java
index 8aae80c8cbeb21d9133b41734dcb89bf92ca7dfd..0c924375c0e67c38aee383b9f69d8479553c18cb 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DateConverterTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/common/DateConverterTest.java
@@ -1,7 +1,8 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.common;
 
 import static org.assertj.core.api.Assertions.*;
 
+import java.time.ZonedDateTime;
 import java.util.Optional;
 
 import javax.xml.datatype.DatatypeConfigurationException;
@@ -55,18 +56,37 @@ class DateConverterTest {
 			assertThat(converted).isEmpty();
 		}
 
+		private Optional<XMLGregorianCalendar> callConverter(String dateStr) {
+			return converter.convertGermanFormatToISO(dateStr);
+		}
+	}
+
+	@Nested
+	class TestCreateDatatypeFactory {
+
 		@Test
 		void shouldThrowTechnicalException() {
 			try (MockedStatic<DatatypeFactory> datatypeFactory = Mockito.mockStatic(DatatypeFactory.class)) {
 				datatypeFactory.when(DatatypeFactory::newInstance).thenThrow(DatatypeConfigurationException.class);
 
-				assertThatThrownBy(() -> callConverter(DATE)).isInstanceOf(TechnicalException.class);
+				assertThatThrownBy(() -> converter.createDatatypeFactory()).isInstanceOf(TechnicalException.class);
 			}
 		}
+	}
 
-		private Optional<XMLGregorianCalendar> callConverter(String dateStr) {
-			return converter.convertGermanFormatToISO(dateStr);
+	@Nested
+	class TestToXmlGregorianCalendar {
+
+		@Test
+		void shouldConvertZonedDateTime() {
+			var date = ZonedDateTime.now();
+
+			var xmlGregorianCalendar = converter.toXmlGregorianCalendar(date);
+
+			assertThat(xmlGregorianCalendar.getYear()).isEqualTo(date.getYear());
+			assertThat(xmlGregorianCalendar.getMonth()).isEqualTo(date.getMonthValue());
+			assertThat(xmlGregorianCalendar.getDay()).isEqualTo(date.getDayOfMonth());
 		}
-	}
 
+	}
 }
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeAbgabe0401CreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeAbgabe0401CreatorTest.java
deleted file mode 100644
index f34a7d3b963dfdcecd235f52e49cbf94d6de6bb9..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeAbgabe0401CreatorTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-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 de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
-import de.xoev.xdomea.AbgabeAbgabe0401.Schriftgutobjekt;
-import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
-
-class AbgabeAbgabe0401CreatorTest {
-
-	@InjectMocks
-	private AbgabeAbgabe0401Creator creator;
-
-	@Mock
-	private SchriftgutobjektCreator schriftgutobjektCreator;
-
-	@Mock
-	private AnwendungsspezifischeErweiterungTypeCreator anwendungsspezifischeErweiterungTypeCreator;
-
-	@Nested
-	class TestCreate {
-
-		private final VorgangWithEingang vorgangWithEingang = VorgangWithEingangTestFactory.create();
-
-		private final AnwendungsspezifischeErweiterungType anwendungsspezifischeErweiterung = AnwendungsspezifischeErweiterungTypeTestFactory.create();
-		private final Schriftgutobjekt schriftgutobjekt = SchriftgutobjektTestFactory.create();
-
-		@BeforeEach
-		void init() {
-			when(anwendungsspezifischeErweiterungTypeCreator.create(vorgangWithEingang)).thenReturn(
-					anwendungsspezifischeErweiterung);
-		}
-
-		@Test
-		void shouldCallMapper() {
-			creator.create(vorgangWithEingang);
-
-			verify(anwendungsspezifischeErweiterungTypeCreator).create(vorgangWithEingang);
-		}
-
-		@Test
-		void shouldCreateSchriftgutobjekt() {
-			creator.create(vorgangWithEingang);
-
-			verify(schriftgutobjektCreator).create(vorgangWithEingang, anwendungsspezifischeErweiterung);
-		}
-
-		@Test
-		void shouldHaveSchriftgutobjekt() {
-			doReturn(schriftgutobjekt).when(schriftgutobjektCreator).create(vorgangWithEingang, anwendungsspezifischeErweiterung);
-
-			var abgabe = creator.create(vorgangWithEingang);
-
-			assertThat(abgabe.getSchriftgutobjekt().get(0)).isEqualTo(schriftgutobjekt);
-		}
-	}
-
-}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e1524d0fd79e5b379471b53e09b436307a0ef7b
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java
@@ -0,0 +1,59 @@
+package de.ozgcloud.alfa.export;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import de.xoev.xdomea.DokumentType;
+import de.xoev.xdomea.NkAbgabeType;
+import de.xoev.xdomea.VorgangType;
+
+public class AbgabeCreatorTest {
+
+	private final AbgabeCreator abgabeCreator = AbgabeCreator.createAbgabeCreator();
+	private final NkAbgabeType kopfType = new NkAbgabeType();
+	private final VorgangType vorgangType = new VorgangType();
+	private final List<DokumentType> dokumentTypes = List.of(new DokumentType(), new DokumentType());
+
+	@Test
+	void shouldSetKopf() {
+		var abgabeType = abgabeCreator.withKopf(kopfType).create();
+
+		assertThat(abgabeType.getKopf()).isEqualTo(kopfType);
+	}
+
+	@Test
+	void shoulAddOneSchriftgutobjekt() {
+		var abgabeType = abgabeCreator.withVorgang(vorgangType).create();
+
+		assertThat(abgabeType.getSchriftgutobjekt()).size().isEqualTo(1);
+	}
+
+	@Test
+	void shouldAddOnlyOneSchriftgutobjekt() {
+		var abgabeType = abgabeCreator.withVorgang(vorgangType).withVorgang(vorgangType).create();
+
+		assertThat(abgabeType.getSchriftgutobjekt()).size().isEqualTo(1);
+	}
+
+	@Test
+	void shouldSetVorgang() {
+		var abgabeType = abgabeCreator.withVorgang(vorgangType).create();
+
+		assertThat(abgabeType.getSchriftgutobjekt().get(0).getVorgang()).isEqualTo(vorgangType);
+	}
+
+	@Test
+	void shouldAddDokumentTypes() {
+		var abgabeType = abgabeCreator.withVorgang(vorgangType).withDokumentTypes(dokumentTypes.stream()).create();
+
+		assertThat(abgabeType.getSchriftgutobjekt().get(0).getVorgang().getDokument()).isEqualTo(dokumentTypes);
+	}
+
+	@Test
+	void shouldThrowExceptionIfVorgangNotSet() {
+		assertThatThrownBy(() -> abgabeCreator.withDokumentTypes(dokumentTypes.stream())).isExactlyInstanceOf(IllegalStateException.class);
+	}
+}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DokumentTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DokumentTypeCreatorTest.java
deleted file mode 100644
index 45015d4e9a5f95dd66bf6bc57c7e4f3970067425..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DokumentTypeCreatorTest.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.StringUtils;
-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.mockito.Spy;
-
-import de.ozgcloud.alfa.common.TestUtils;
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
-import de.ozgcloud.alfa.vorgang.EingangTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
-import de.xoev.xdomea.AllgemeineMetadatenType;
-import de.xoev.xdomea.DokumentType;
-import de.xoev.xdomea.IdentifikationObjektType;
-import de.xoev.xdomea.VersionType;
-
-class DokumentTypeCreatorTest {
-
-	@Spy
-	@InjectMocks
-	private DokumentTypeCreator creator;
-
-	@Mock
-	private ExportFileService exportFileService;
-
-	@Mock
-	private UUIDConverter uuidConverter;
-
-	@Mock
-	private VersionTypeCreator versionTypeCreator;
-
-	@Nested
-	class TestCreate {
-
-		@Nested
-		class WhenAllVorgangDataAvailable {
-			private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
-			private final OzgFile ozgFile = OzgFileTestFactory.create();
-
-			@BeforeEach
-			void init() {
-				when(exportFileService.getAllPdfs(EingangTestFactory.ID)).thenReturn(Stream.of(ozgFile));
-			}
-
-			@Test
-			void shouldLoadlAllPdfs() {
-				creator.create(vorgang);
-
-				verify(exportFileService).getAllPdfs(EingangTestFactory.ID);
-			}
-
-			@Test
-			void shouldCreateDokumentType() {
-				creator.create(vorgang);
-
-				verify(creator).createDokumentType(1, vorgang, ozgFile);
-			}
-		}
-
-		@Nested
-		class WhenEingangIsNull {
-
-			@Test
-			void shouldNotLoadAnyPdf() {
-				creator.create(VorgangWithEingang.builder().eingang(null).build());
-
-				verify(exportFileService, never()).getAllPdfs(EingangTestFactory.ID);
-			}
-
-			@Test
-			void shouldReturnEmptyStreamIfEingangNull() {
-				var result = creator.create(VorgangWithEingang.builder().eingang(null).build());
-
-				assertThat(result).isEmpty();
-			}
-		}
-
-	}
-
-	@Nested
-	class CreateDokumentType {
-
-		private final IdentifikationObjektType identifikationObjekt = IdentifikationObjektTypeTestFactory.create();
-		private final AllgemeineMetadatenType allgemeineMetadaten = AllgemeineMetadatenTypeTestFactory.create();
-		private final OzgFile ozgFile = OzgFileTestFactory.create();
-		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
-		private final VersionType version = VersionTypeTestFactory.create();
-		private final int DOKUMENT_ORDINAL_NUMBER = 1;
-
-		@BeforeEach
-		void init() {
-			doReturn(identifikationObjekt).when(creator).createIdentifikation(DOKUMENT_ORDINAL_NUMBER, OzgFileTestFactory.ID.toString());
-			doReturn(allgemeineMetadaten).when(creator).createAllgemeineMetadaten(ozgFile);
-
-			when(versionTypeCreator.create(vorgang, ozgFile)).thenReturn(version);
-		}
-
-		@Test
-		void shouldCreateIdentifikation() {
-			create();
-
-			verify(creator).createIdentifikation(DOKUMENT_ORDINAL_NUMBER, OzgFileTestFactory.ID.toString());
-		}
-
-		@Test
-		void shouldHaveIdentifikation() {
-			var dokument = create();
-
-			assertThat(dokument.getIdentifikation()).isEqualTo(identifikationObjekt);
-		}
-
-		@Test
-		void shouldCreateAllgemeineMetadaten() {
-			create();
-
-			verify(creator).createAllgemeineMetadaten(ozgFile);
-		}
-
-		@Test
-		void shouldHaveAllgemeineMetadaten() {
-			var dokument = create();
-
-			assertThat(dokument.getAllgemeineMetadaten()).isEqualTo(allgemeineMetadaten);
-		}
-
-		@Test
-		void shouldCreateVersion() {
-			create();
-
-			verify(versionTypeCreator).create(vorgang, ozgFile);
-		}
-
-		@Test
-		void shouldHaveVersion() {
-			var dokument = create();
-
-			assertThat(dokument.getVersion()).containsExactly(version);
-		}
-
-		private DokumentType create() {
-			return creator.createDokumentType(DOKUMENT_ORDINAL_NUMBER, vorgang, ozgFile);
-		}
-	}
-
-	@Nested
-	class TestCreateIdentifikation {
-
-		private final String FILE_ID = "64a820d36285172ac02826d0";
-		private final String FILE_UUID = "64a820d3-6285-172a-c028-0000000026d0";
-		private final int DOKUMENT_ORDINAL_NUMBER = 1;
-
-		@BeforeEach
-		void init() {
-			when(uuidConverter.fromObjectId(FILE_ID)).thenReturn(FILE_UUID);
-		}
-
-		@Test
-		void shouldConvertObjectId() {
-			create();
-
-			verify(uuidConverter).fromObjectId(FILE_ID);
-		}
-
-		@Test
-		void shouldHaveId() {
-			var identifikation = create();
-
-			assertThat(identifikation.getID()).matches(TestUtils.UUID_REGEX).isEqualTo(FILE_UUID);
-		}
-
-		@Test
-		void shouldHaveNummerImUebergeordnetenContainer() {
-			var identifikation = create();
-
-			assertThat(identifikation.getNummerImUebergeordnetenContainer()).isEqualTo(DOKUMENT_ORDINAL_NUMBER);
-		}
-
-		private IdentifikationObjektType create() {
-			return creator.createIdentifikation(DOKUMENT_ORDINAL_NUMBER, FILE_ID);
-		}
-	}
-
-	@Nested
-	class TestCreateAllgemeineMetadaten {
-
-		private final OzgFile ozgFile = OzgFileTestFactory.create();
-
-		@Test
-		void shouldHaveBetreff() {
-			var allgemeineMetadaten = creator.createAllgemeineMetadaten(ozgFile);
-
-			assertThat(allgemeineMetadaten.getBetreff()).isEqualTo(OzgFileTestFactory.NAME);
-		}
-
-		@Test
-		void shouldHaveKennzeichen() {
-			var allgemeineMetadaten = creator.createAllgemeineMetadaten(ozgFile);
-
-			assertThat(allgemeineMetadaten.getKennzeichen()).isEmpty();
-		}
-
-		@Test
-		void shouldHaveBemerkung() {
-			var allgemeineMetadaten = creator.createAllgemeineMetadaten(ozgFile);
-
-			assertThat(allgemeineMetadaten.getBemerkung()).isEmpty();
-		}
-
-		@Test
-		void shouldHaveMedium() {
-			var allgemeineMetadaten = creator.createAllgemeineMetadaten(ozgFile);
-
-			assertThat(allgemeineMetadaten.getMedium().getCode()).isEqualTo(VorgangTypeCreator.ALLGEMEINE_METADATEN_MEDIUM_CODE);
-		}
-
-	}
-
-}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XmlMarshallerConfigurationTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportConfigurationTest.java
similarity index 79%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XmlMarshallerConfigurationTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportConfigurationTest.java
index 46ddabac96c193f78b8ec3e8a448cbb68897c90f..ea207d98c6d2ef4494aaf13ed8766a35124bf780 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XmlMarshallerConfigurationTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportConfigurationTest.java
@@ -5,8 +5,6 @@ import static org.mockito.Mockito.*;
 
 import java.util.Map;
 
-import jakarta.xml.bind.Marshaller;
-
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -15,11 +13,13 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.oxm.jaxb.Jaxb2Marshaller;
 
-class XmlMarshallerConfigurationTest {
+import jakarta.xml.bind.Marshaller;
+
+class ExportConfigurationTest {
 
 	@Spy
 	@InjectMocks
-	private XDomeaXmlMarshallerConfiguration configuration;
+	private ExportConfiguration configuration;
 
 	@Mock
 	private XDomeaNamespacePrefixMapper prefixMapper;
@@ -31,14 +31,14 @@ class XmlMarshallerConfigurationTest {
 		void shouldFromatMarshalledXml() {
 			var props = configuration.createMarshallerProperties();
 
-			assertThat(props).containsEntry(Marshaller.JAXB_FORMATTED_OUTPUT, XDomeaXmlMarshallerConfiguration.JAXB_FORMATTED_OUTPUT);
+			assertThat(props).containsEntry(Marshaller.JAXB_FORMATTED_OUTPUT, ExportConfiguration.JAXB_FORMATTED_OUTPUT);
 		}
 
 		@Test
 		void shouldUseNamespacePrefixMapper() {
 			var props = configuration.createMarshallerProperties();
 
-			assertThat(props).containsEntry(XDomeaXmlMarshallerConfiguration.PROPERTY_NAMESPACE_PREFIX_MAPPER, prefixMapper);
+			assertThat(props).containsEntry(ExportConfiguration.PROPERTY_NAMESPACE_PREFIX_MAPPER, prefixMapper);
 		}
 	}
 
@@ -56,7 +56,7 @@ class XmlMarshallerConfigurationTest {
 		void shouldSetContextPath() {
 			var marshaller = configuration.marshaller();
 
-			assertThat(marshaller.getContextPath()).isEqualTo(XDomeaXmlMarshallerConfiguration.CONTEXT_PATH);
+			assertThat(marshaller.getContextPath()).isEqualTo(ExportConfiguration.CONTEXT_PATH);
 		}
 
 		@Test
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportDataTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportDataTestFactory.java
index 2be3ee462e90de9997dff74f5b9d145cbb873256..4843d830ed6dc1f31db0b27359c2352c9bcf6d90 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportDataTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportDataTestFactory.java
@@ -4,22 +4,22 @@ import java.util.stream.Stream;
 
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
+import de.xoev.xdomea.AbgabeAbgabe0401;
 
 class ExportDataTestFactory {
 
 	public static final String EXPORT_FILENAME = "file.zip";
-	public static final String XML_FILE_CONTENT = "<xml></xml>";
 	public static final OzgFile OZG_FILE = OzgFileTestFactory.create();
-	public static final VorgangWithEingang VORGANG = VorgangWithEingangTestFactory.create();
+	public static final AbgabeAbgabe0401 ABGABE = AbgabeAbgabe0401TestFactory.create();
 
 	public static ExportData create() {
 		return createBuilder().build();
 	}
 
 	public static ExportData.ExportDataBuilder createBuilder() {
-		return ExportData.builder().exportFilename(EXPORT_FILENAME).xmlFileContent(XML_FILE_CONTENT).vorgang(VORGANG)
+		return ExportData.builder()
+				.exportFilename(EXPORT_FILENAME)
+				.abgabe(ABGABE)
 				.exportFiles(Stream.of(OZG_FILE));
 	}
 }
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java
index 66d6480e708665d465935f20010c1bdc5cba38f6..229903bef4f56342d5e68f432ac0d03814aa6055 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java
@@ -9,7 +9,9 @@ import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
+import de.ozgcloud.alfa.common.ExportFilenameGenerator;
 import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.UUIDConverter;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XDomeaServiceTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java
similarity index 71%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XDomeaServiceTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java
index 91433d1db42f57c62da258afcb7570b76b7f7351..2a09022daa695900b8d0818ec1ff4919727157e3 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XDomeaServiceTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java
@@ -14,6 +14,7 @@ import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -22,37 +23,41 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.MockedStatic;
 import org.mockito.Spy;
 
+import de.ozgcloud.alfa.common.ExportFilenameGenerator;
 import de.ozgcloud.alfa.common.TestUtils;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
+import de.ozgcloud.alfa.file.ExportFileService;
+import de.ozgcloud.alfa.vorgang.EingangHeaderTestFactory;
 import de.ozgcloud.alfa.vorgang.EingangTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangController;
+import de.ozgcloud.alfa.vorgang.ExportVorgangService;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
 import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
 import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.xoev.xdomea.AbgabeAbgabe0401;
+import de.xoev.xdomea.DokumentType;
+import de.xoev.xdomea.NkAbgabeType;
+import de.xoev.xdomea.VorgangType;
 import lombok.SneakyThrows;
 
-class XDomeaServiceTest {
+class ExportServiceTest {
 
 	@Spy
 	@InjectMocks
-	private XDomeaService service;
+	private ExportService service;
 
 	@Mock
 	private XDomeaXmlMarshaller XDomeaXmlMarshaller;
 
 	@Mock
-	private VorgangController vorgangController;
-
-	@Mock
-	private AbgabeAbgabe0401Creator abgabeCreator;
+	private ExportFileService exportFileService;
 
 	@Mock
-	private ExportFileService exportFileService;
+	private ExportVorgangService exportVorgangService;
 
 	@Mock
 	private ExportFilenameGenerator exportFilenameGenerator;
@@ -106,30 +111,41 @@ class XDomeaServiceTest {
 
 		private static final String FILENAME_ID = UUID.randomUUID().toString();
 		private static final String FILE_NAME = "file.zip";
-		private static final String XML_STRING = "<xml>";
 		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
+		private final VorgangType vorgangType = new VorgangType();
+		private final NkAbgabeType kopfType = new NkAbgabeType();
 		private final Stream<OzgFile> ozgFiles = Stream.of(OzgFileTestFactory.create());
+		private final Stream<DokumentType> dokumentTypes = Stream.of(DokumentTypeTestFactory.create());
+		private final AbgabeAbgabe0401 abgabeAbgabe0401 = AbgabeAbgabe0401TestFactory.create();
+
+		private MockedStatic<AbgabeCreator> abgabeCreatorStatic;
+
+		@Spy
+		private AbgabeCreator abgabeCreator;
 
 		@BeforeEach
 		void setUp() {
-			when(exportFileService.getAllPdfs(EingangTestFactory.ID)).thenReturn(ozgFiles);
-			when(vorgangController.getVorgang(VorgangHeaderTestFactory.ID)).thenReturn(vorgang);
-			doReturn(XML_STRING).when(service).createXmlContent(vorgang);
-			doReturn(FILE_NAME).when(service).buildXmlFilename(FILENAME_ID);
+			when(exportVorgangService.getVorgang(any())).thenReturn(vorgang);
+			when(exportVorgangService.createVorgangType(any())).thenReturn(vorgangType);
+			when(exportVorgangService.createKopf(any())).thenReturn(kopfType);
+			when(exportFileService.getAllPdfs(any())).thenReturn(ozgFiles);
+			when(exportFileService.createDokumentTypes(any(), any())).thenReturn(dokumentTypes);
+			doReturn(FILE_NAME).when(service).buildXmlFilename(any());
+			abgabeCreatorStatic = mockStatic(AbgabeCreator.class);
+			abgabeCreatorStatic.when(AbgabeCreator::createAbgabeCreator).thenReturn(abgabeCreator);
+			doReturn(abgabeAbgabe0401).when(abgabeCreator).create();
 		}
 
-		@Test
-		void shouldLoadVorgang() {
-			callService();
-
-			verify(vorgangController).getVorgang(VorgangHeaderTestFactory.ID);
+		@AfterEach
+		void cleanup() {
+			abgabeCreatorStatic.close();
 		}
 
 		@Test
-		void shouldCreateXmlStringContent() {
+		void shouldLoadVorgang() {
 			callService();
 
-			verify(service).createXmlContent(vorgang);
+			verify(exportVorgangService).getVorgang(VorgangHeaderTestFactory.ID);
 		}
 
 		@Test
@@ -147,28 +163,70 @@ class XDomeaServiceTest {
 		}
 
 		@Test
-		void shouldContainsVorgang() {
-			var exportData = callService();
+		void shouldCreateKopf() {
+			callService();
+
+			verify(exportVorgangService).createKopf(vorgang);
+		}
+
+		@Test
+		void shouldCreateVorgangType() {
+			callService();
+
+			verify(exportVorgangService).createVorgangType(vorgang);
+		}
+
+		@Test
+		void shouldCreateDokumentTypes() {
+			callService();
+
+			verify(exportFileService).createDokumentTypes(ozgFiles, EingangHeaderTestFactory.FORM_ENGINE_NAME);
+		}
+
+		@Test
+		void shouldSetKopf() {
+			callService();
+
+			verify(abgabeCreator).withKopf(kopfType);
+		}
+
+		@Test
+		void shouldSetVorgang() {
+			callService();
 
-			assertThat(exportData.getVorgang()).isEqualTo(vorgang);
+			verify(abgabeCreator).withVorgang(vorgangType);
 		}
 
 		@Test
-		void shouldContainsXmlContent() {
+		void shouldSetDokumentTypes() {
+			callService();
+
+			verify(abgabeCreator).withDokumentTypes(dokumentTypes);
+		}
+
+		@Test
+		void shouldCreateAbgabe() {
+			callService();
+
+			verify(abgabeCreator).create();
+		}
+
+		@Test
+		void shouldContainAbgabe() {
 			var exportData = callService();
 
-			assertThat(exportData.getXmlFileContent()).isEqualTo(XML_STRING);
+			assertThat(exportData.getAbgabe()).isEqualTo(abgabeAbgabe0401);
 		}
 
 		@Test
-		void shouldContainsExportFilename() {
+		void shouldContainExportFilename() {
 			var exportData = callService();
 
 			assertThat(exportData.getExportFilename()).isEqualTo(FILE_NAME);
 		}
 
 		@Test
-		void shouldContainsExportExportFiles() {
+		void shouldContainExportExportFiles() {
 			var exportData = callService();
 
 			assertThat(exportData.getExportFiles()).isEqualTo(ozgFiles);
@@ -188,7 +246,7 @@ class XDomeaServiceTest {
 		void shouldMatchPattern() {
 			var filename = service.buildXmlFilename(UUID.randomUUID().toString());
 
-			assertThat(filename).matches(TestUtils.uuidRegexWithSuffix(XDomeaService.EXPORT_FILENAME_SUFFIX));
+			assertThat(filename).matches(TestUtils.uuidRegexWithSuffix(ExportService.EXPORT_FILENAME_SUFFIX));
 		}
 	}
 
@@ -198,12 +256,8 @@ class XDomeaServiceTest {
 
 		private static final String XML_STRING = "<xml>";
 
-		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
-		private final AbgabeAbgabe0401 abgabe = AbgabeAbgabe0401TestFactory.create();
-
 		@BeforeEach
 		void init() {
-			doReturn(abgabe).when(abgabeCreator).create(vorgang);
 			when(XDomeaXmlMarshaller.marshal(any())).thenReturn(XML_STRING);
 		}
 
@@ -211,7 +265,7 @@ class XDomeaServiceTest {
 		void shouldCallXmlMarshaller() {
 			callService();
 
-			verify(XDomeaXmlMarshaller).marshal(abgabe);
+			verify(XDomeaXmlMarshaller).marshal(ExportDataTestFactory.ABGABE);
 		}
 
 		@Test
@@ -221,21 +275,15 @@ class XDomeaServiceTest {
 			assertThat(result).isEqualTo(XML_STRING);
 		}
 
-		@Test
-		void shouldCallAbgabeCreator() {
-			callService();
-
-			verify(abgabeCreator).create(vorgang);
-		}
-
 		private String callService() {
-			return service.createXmlContent(vorgang);
+			return service.createXmlContent(ExportDataTestFactory.ABGABE);
 		}
 	}
 
 	@Nested
 	class TestCreateZipFile {
 
+		private static final String XML_FILE_CONTENT = "<xml></xml>";
 		private static final String XML_STRING = "<xml>";
 		private final ExportData exportData = ExportDataTestFactory.create();
 
@@ -245,14 +293,22 @@ class XDomeaServiceTest {
 		@SneakyThrows
 		@BeforeEach
 		void setUp() {
+			when(service.createXmlContent(ExportDataTestFactory.ABGABE)).thenReturn(XML_FILE_CONTENT);
 			doNothing().when(service).putOzgFileIntoZip(any(OzgFile.class), any(ZipOutputStream.class));
 		}
 
+		@Test
+		void shouldCreateXmlStringContent() {
+			callService();
+
+			verify(service).createXmlContent(ExportDataTestFactory.ABGABE);
+		}
+
 		@Test
 		void shouldCreateZipEntry() throws IOException {
 			callService();
 
-			verify(service).putZipEntry(eq(ExportDataTestFactory.EXPORT_FILENAME), eq(ExportDataTestFactory.XML_FILE_CONTENT),
+			verify(service).putZipEntry(eq(ExportDataTestFactory.EXPORT_FILENAME), eq(XML_FILE_CONTENT),
 					any(ZipOutputStream.class));
 		}
 
@@ -260,7 +316,7 @@ class XDomeaServiceTest {
 		void shouldCreateZipOutputStream() throws IOException {
 			callService();
 
-			verify(service).putZipEntry(eq(ExportDataTestFactory.EXPORT_FILENAME), eq(ExportDataTestFactory.XML_FILE_CONTENT),
+			verify(service).putZipEntry(eq(ExportDataTestFactory.EXPORT_FILENAME), eq(XML_FILE_CONTENT),
 					zipOutputStreamArgumentCaptor.capture());
 			assertThat(zipOutputStreamArgumentCaptor.getValue()).isInstanceOf(ZipOutputStream.class);
 		}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java
index 9c273905bf2471409b2df42c41211f5df58cdd84..23b527f9e770d1eb366469f71889ac5ac4a2e6e5 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java
@@ -31,7 +31,7 @@ class ExportVorgangControllerTest {
 	private ExportVorgangController controller;
 
 	@Mock
-	private XDomeaService xDomeaService;
+	private ExportService xDomeaService;
 
 	private MockMvc mockMvc;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FormatTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FormatTypeCreatorTest.java
deleted file mode 100644
index a15c43215ff5d4ebfd44461fc74a75d44fb70010..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FormatTypeCreatorTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import org.apache.commons.lang3.StringUtils;
-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.mockito.Spy;
-
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
-import de.xoev.xdomea.PrimaerdokumentType;
-
-class FormatTypeCreatorTest {
-
-	@Spy
-	@InjectMocks
-	private FormatTypeCreator creator;
-
-	@Mock
-	private PrimaerdokumentTypeCreator primaerdokumentTypeCreator;
-
-	@Nested
-	class TestCreate {
-
-		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
-		private final OzgFile ozgFile = OzgFileTestFactory.create();
-
-		private final PrimaerdokumentType primaerdokument = PrimaerdokumentTypeTestFactory.create();
-
-		@BeforeEach
-		void init() {
-			when(primaerdokumentTypeCreator.create(vorgang, ozgFile)).thenReturn(primaerdokument);
-		}
-
-		@Test
-		void shouldCreatePrimaerdokument() {
-			creator.create(vorgang, ozgFile);
-
-			verify(primaerdokumentTypeCreator).create(vorgang, ozgFile);
-		}
-
-		@Test
-		void shouldHavePrimaerdokumentType() {
-			var format = creator.create(vorgang, ozgFile);
-
-			assertThat(format.getPrimaerdokument()).isEqualTo(primaerdokument);
-		}
-
-		@Test
-		void shouldHaveName() {
-			var format = creator.create(vorgang, ozgFile);
-
-			assertThat(format.getName()).usingRecursiveComparison().isEqualTo(DateiformatCode.PDF.createDateiformatCodeType());
-		}
-
-		@Test
-		void shouldHaveSonstigerName() {
-			var format = creator.create(vorgang, ozgFile);
-
-			assertThat(format.getSonstigerName()).isEmpty();
-		}
-
-		@Test
-		void shouldHaveVersion() {
-			var format = creator.create(vorgang, ozgFile);
-
-			assertThat(format.getVersion()).isEmpty();
-		}
-	}
-
-}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeCreatorTest.java
deleted file mode 100644
index db307b1e5da896283a48d60c7e31da70ecba26d9..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeCreatorTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-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.mockito.Spy;
-
-import de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
-import de.ozgcloud.alfa.vorgang.EingangHeaderTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
-
-class PrimaerdokumentTypeCreatorTest {
-
-	@Spy
-	@InjectMocks
-	private PrimaerdokumentTypeCreator creator;
-
-	@Mock
-	private ExportFilenameGenerator exportFilenameGenerator;
-
-	@Nested
-	class TestCreate {
-
-		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
-		private final OzgFile ozgFile = OzgFileTestFactory.create();
-
-		@BeforeEach
-		void init() {
-			when(exportFilenameGenerator.generateExportFilename(ozgFile)).thenReturn(ozgFile.getName());
-		}
-
-		@Test
-		void shouldGenerateExportFilename() {
-			creator.create(vorgang, ozgFile);
-
-			verify(exportFilenameGenerator).generateExportFilename(ozgFile);
-		}
-
-		@Test
-		void shouldHaveDateiname() {
-			var primaerdokument = creator.create(vorgang, ozgFile);
-
-			assertThat(primaerdokument.getDateiname()).isEqualTo(ozgFile.getName());
-		}
-
-		@Test
-		void shouldHaveDateinameOriginal() {
-			var primaerdokument = creator.create(vorgang, ozgFile);
-
-			assertThat(primaerdokument.getDateinameOriginal()).isEqualTo(ozgFile.getName());
-		}
-
-		@Test
-		void shouldHaveErsteller() {
-			var primaerdokument = creator.create(vorgang, ozgFile);
-
-			assertThat(primaerdokument.getErsteller()).isEqualTo(EingangHeaderTestFactory.FORM_ENGINE_NAME);
-		}
-	}
-}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/SchriftgutobjektCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/SchriftgutobjektCreatorTest.java
deleted file mode 100644
index 1ea75ceee7e8b37bf123339fd9fc0ee60503e722..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/SchriftgutobjektCreatorTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
-import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
-import de.xoev.xdomea.VorgangType;
-
-class SchriftgutobjektCreatorTest {
-
-	@InjectMocks
-	private SchriftgutobjektCreator creator;
-
-	@Mock
-	private VorgangTypeCreator vorgangTypeCreator;
-
-	@Nested
-	class TestCreate {
-
-		private final VorgangWithEingang vorgangWithEingang = VorgangWithEingangTestFactory.create();
-
-		private final VorgangType vorgang = VorgangTypeTestFactory.create();
-		private final AnwendungsspezifischeErweiterungType anwendungsspezifischeErweiterung = AnwendungsspezifischeErweiterungTypeTestFactory.create();
-
-		@Test
-		void shouldCreateVorgangType() {
-			creator.create(vorgangWithEingang, anwendungsspezifischeErweiterung);
-
-			verify(vorgangTypeCreator).create(vorgangWithEingang, anwendungsspezifischeErweiterung);
-		}
-
-		@Test
-		void shouldHaveVorgangType() {
-			doReturn(vorgang).when(vorgangTypeCreator).create(vorgangWithEingang, anwendungsspezifischeErweiterung);
-
-			var schriftgutobjekt = creator.create(vorgangWithEingang, anwendungsspezifischeErweiterung);
-
-			assertThat(schriftgutobjekt.getVorgang()).isEqualTo(vorgang);
-		}
-
-	}
-
-}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/SchriftgutobjektTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/SchriftgutobjektTestFactory.java
deleted file mode 100644
index 83bb68a9ef51e43002b1ab959c0f985f7e8236ae..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/SchriftgutobjektTestFactory.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import de.xoev.xdomea.AbgabeAbgabe0401.Schriftgutobjekt;
-
-public class SchriftgutobjektTestFactory {
-
-	public static Schriftgutobjekt create() {
-		return new Schriftgutobjekt();
-	}
-}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java
index 9d6e44fb53c75d36b71fcfd4e8e66ea90f07f188..27a76cf3903e7932b0e713159ad1a14730f891fe 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java
@@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 
 import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.UUIDConverter;
 
 class UUIDConverterTest {
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VersionTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VersionTypeCreatorTest.java
deleted file mode 100644
index bd1f17cb080e3fbc887dbd4cc9cdb6b9dec16f1c..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VersionTypeCreatorTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-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 de.ozgcloud.alfa.common.file.OzgFile;
-import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
-import de.xoev.xdomea.FormatType;
-
-class VersionTypeCreatorTest {
-
-	@InjectMocks
-	private VersionTypeCreator creator;
-
-	@Mock
-	private FormatTypeCreator formatTypeCreator;
-
-	@Nested
-	class TestCreate {
-
-		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
-		private final OzgFile ozgFile = OzgFileTestFactory.create();
-		private final FormatType formatType = FormaTypeTestFactory.create();
-
-		@BeforeEach
-		void init() {
-			when(formatTypeCreator.create(vorgang, ozgFile)).thenReturn(formatType);
-		}
-
-		@Test
-		void shouldHaveNummer() {
-			var version = creator.create(vorgang, ozgFile);
-
-			assertThat(version.getNummer()).isEqualTo(VersionTypeCreator.NUMMER);
-		}
-
-		@Test
-		void shouldCreateFormatType() {
-			creator.create(vorgang, ozgFile);
-
-			verify(formatTypeCreator).create(vorgang, ozgFile);
-		}
-
-		@Test
-		void shouldHaveFormatType() {
-			var version = creator.create(vorgang, ozgFile);
-
-			assertThat(version.getFormat()).containsExactly(formatType);
-		}
-	}
-
-}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DateiformatCodeTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/DateiformatCodeTest.java
similarity index 96%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DateiformatCodeTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/DateiformatCodeTest.java
index 8fefefe8e4ae869abfc6a4242d233accb64cdef4..2bc5492714bb1ee3a0e19d9e237624ec16d382c8 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/DateiformatCodeTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/DateiformatCodeTest.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/DokumentTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/DokumentTypeCreatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2061791699c876777ec156f2958653611478847
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/DokumentTypeCreatorTest.java
@@ -0,0 +1,286 @@
+package de.ozgcloud.alfa.file;
+
+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.BeforeEach;
+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.alfa.common.ExportFilenameGenerator;
+import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.UUIDConverter;
+import de.ozgcloud.alfa.common.file.OzgFile;
+import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
+import de.ozgcloud.alfa.export.AllgemeineMetadatenTypeTestFactory;
+import de.ozgcloud.alfa.export.IdentifikationObjektTypeTestFactory;
+import de.xoev.xdomea.AllgemeineMetadatenType;
+import de.xoev.xdomea.DokumentType;
+import de.xoev.xdomea.FormatType;
+import de.xoev.xdomea.IdentifikationObjektType;
+import de.xoev.xdomea.PrimaerdokumentType;
+import de.xoev.xdomea.VersionType;
+
+class DokumentTypeCreatorTest {
+
+	private static final int DOKUMENT_ORDINAL_NUMBER = 1;
+	private static final String FORM_ENGINE_NAME = "DUMMY_NAME";
+
+	private final OzgFile ozgFile = OzgFileTestFactory.create();
+	private final DokumentTypeCreator.MappingData mappingData = new DokumentTypeCreator.MappingData(ozgFile, DOKUMENT_ORDINAL_NUMBER, FORM_ENGINE_NAME);
+
+	@Spy
+	@InjectMocks
+	private DokumentTypeCreator creator;
+
+	@Mock
+	private UUIDConverter uuidConverter;
+
+	@Mock
+	private ExportFilenameGenerator exportFilenameGenerator;
+
+	@Nested
+	class TestCreate {
+
+		private final OzgFile ozgFile1 = OzgFileTestFactory.create();
+		private final OzgFile ozgFile2 = OzgFileTestFactory.create();
+		private final List<OzgFile> ozgFiles = List.of(ozgFile1, ozgFile2);
+		private final DokumentType dokumentType1 = new DokumentType();
+		private final DokumentType dokumentType2 = new DokumentType();
+
+		@BeforeEach
+		void init() {
+			doReturn(dokumentType1, dokumentType2).when(creator).createDokumentType(any());
+		}
+
+		@Test
+		void shouldCallCreateDokumentType() {
+			create().toList(); // call toList() to finalize stream
+
+			verify(creator).createDokumentType(new DokumentTypeCreator.MappingData(ozgFile1, 1, FORM_ENGINE_NAME));
+			verify(creator).createDokumentType(new DokumentTypeCreator.MappingData(ozgFile2, 2, FORM_ENGINE_NAME));
+		}
+
+		@Test
+		void shouldReturnDocumentTypes() {
+			var dokumentTypes = create().toList();
+
+			assertThat(dokumentTypes.get(0)).isEqualTo(dokumentType1);
+			assertThat(dokumentTypes.get(1)).isEqualTo(dokumentType2);
+		}
+
+		private Stream<DokumentType> create() {
+			return creator.create(ozgFiles.stream(), FORM_ENGINE_NAME);
+		}
+	}
+
+	@Nested
+	class TestCreateDokumentType {
+
+		private final IdentifikationObjektType identifikationObjekt = IdentifikationObjektTypeTestFactory.create();
+		private final AllgemeineMetadatenType allgemeineMetadaten = AllgemeineMetadatenTypeTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			doReturn(identifikationObjekt).when(creator).createIdentifikation(mappingData);
+			doReturn(allgemeineMetadaten).when(creator).createAllgemeineMetadaten(mappingData);
+		}
+
+		@Test
+		void shouldCreateIdentifikation() {
+			create();
+
+			verify(creator).createIdentifikation(mappingData);
+		}
+
+		@Test
+		void shouldHaveIdentifikation() {
+			var dokument = create();
+
+			assertThat(dokument.getIdentifikation()).isEqualTo(identifikationObjekt);
+		}
+
+		@Test
+		void shouldCreateAllgemeineMetadaten() {
+			create();
+
+			verify(creator).createAllgemeineMetadaten(mappingData);
+		}
+
+		@Test
+		void shouldHaveAllgemeineMetadaten() {
+			var dokument = create();
+
+			assertThat(dokument.getAllgemeineMetadaten()).isEqualTo(allgemeineMetadaten);
+		}
+
+		@Test
+		void shouldHaveVersion() {
+			var dokumentType = create();
+
+			assertThat(dokumentType.getVersion()).size().isEqualTo(1);
+		}
+
+		@Nested
+		class TestVersion {
+
+			@Test
+			void shouldHaveNummer() {
+				assertThat(getVersion().getNummer()).isEqualTo(DokumentTypeCreator.VERSION_NUMMER);
+			}
+
+			@Test
+			void shouldHaveFormat() {
+				assertThat(getVersion().getFormat()).size().isEqualTo(1);
+			}
+		}
+
+		@Nested
+		class TestFormat {
+
+			@Test
+			void shouldHaveName() {
+				assertThat(getFormat().getName()).usingRecursiveComparison().isEqualTo(DateiformatCode.PDF.createDateiformatCodeType());
+			}
+
+			@Test
+			void shouldHaveSonstigerName() {
+				assertThat(getFormat().getSonstigerName()).isEmpty();
+			}
+
+			@Test
+			void shouldHaveVersion() {
+				assertThat(getFormat().getVersion()).isEmpty();
+			}
+
+			@Test
+			void shouldHavePrimaerdokument() {
+				assertThat(getPrimaerdokument()).isNotNull();
+			}
+		}
+
+		@Nested
+		class TestPrimaerdokument {
+
+			@BeforeEach
+			void init() {
+				when(exportFilenameGenerator.generateExportFilename(ozgFile)).thenReturn(ozgFile.getName());
+			}
+
+			@Test
+			void shouldGenerateExportFilename() {
+				create();
+
+				verify(exportFilenameGenerator).generateExportFilename(ozgFile);
+			}
+
+			@Test
+			void shouldHaveDateiname() {
+				assertThat(getPrimaerdokument().getDateiname()).isEqualTo(ozgFile.getName());
+			}
+
+			@Test
+			void shouldHaveDateinameOriginal() {
+				assertThat(getPrimaerdokument().getDateinameOriginal()).isEqualTo(ozgFile.getName());
+			}
+
+			@Test
+			void shouldHaveErsteller() {
+				assertThat(getPrimaerdokument().getErsteller()).isEqualTo(FORM_ENGINE_NAME);
+			}
+
+		}
+
+		private VersionType getVersion() {
+			return create().getVersion().get(0);
+		}
+
+		private FormatType getFormat() {
+			return getVersion().getFormat().get(0);
+		}
+
+		private PrimaerdokumentType getPrimaerdokument() {
+			return getFormat().getPrimaerdokument();
+		}
+
+		private DokumentType create() {
+			return creator.createDokumentType(mappingData);
+		}
+	}
+
+	@Nested
+	class TestCreateIdentifikation {
+
+		private final String FILE_UUID = "64a820d3-6285-172a-c028-0000000026d0";
+
+		@BeforeEach
+		void init() {
+			when(uuidConverter.fromObjectId(OzgFileTestFactory.ID.toString())).thenReturn(FILE_UUID);
+		}
+
+		@Test
+		void shouldConvertObjectId() {
+			create();
+
+			verify(uuidConverter).fromObjectId(OzgFileTestFactory.ID.toString());
+		}
+
+		@Test
+		void shouldHaveId() {
+			var identifikation = create();
+
+			assertThat(identifikation.getID()).matches(TestUtils.UUID_REGEX).isEqualTo(FILE_UUID);
+		}
+
+		@Test
+		void shouldHaveNummerImUebergeordnetenContainer() {
+			var identifikation = create();
+
+			assertThat(identifikation.getNummerImUebergeordnetenContainer()).isEqualTo(DOKUMENT_ORDINAL_NUMBER);
+		}
+
+		private IdentifikationObjektType create() {
+			return creator.createIdentifikation(mappingData);
+		}
+	}
+
+	@Nested
+	class TestCreateAllgemeineMetadaten {
+
+		@Test
+		void shouldHaveBetreff() {
+			var allgemeineMetadaten = creator.createAllgemeineMetadaten(mappingData);
+
+			assertThat(allgemeineMetadaten.getBetreff()).isEqualTo(OzgFileTestFactory.NAME);
+		}
+
+		@Test
+		void shouldHaveKennzeichen() {
+			var allgemeineMetadaten = creator.createAllgemeineMetadaten(mappingData);
+
+			assertThat(allgemeineMetadaten.getKennzeichen()).isEmpty();
+		}
+
+		@Test
+		void shouldHaveBemerkung() {
+			var allgemeineMetadaten = creator.createAllgemeineMetadaten(mappingData);
+
+			assertThat(allgemeineMetadaten.getBemerkung()).isEmpty();
+		}
+
+		@Test
+		void shouldHaveMedium() {
+			var allgemeineMetadaten = creator.createAllgemeineMetadaten(mappingData);
+
+			assertThat(allgemeineMetadaten.getMedium().getCode()).isEqualTo(DokumentTypeCreator.ALLGEMEINE_METADATEN_MEDIUM_CODE);
+		}
+
+	}
+
+}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFileServiceTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/ExportFileServiceTest.java
similarity index 98%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFileServiceTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/ExportFileServiceTest.java
index 45d3e64f283d9140299ec72e58659f7e1a743fa9..4a9ad191a63a1dc143bece4ce2caf39bbaf08e25 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFileServiceTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/ExportFileServiceTest.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FormaTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/FormaTypeTestFactory.java
similarity index 61%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FormaTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/FormaTypeTestFactory.java
index b4c5902e19925829e206e4f3c6cd6d0e19098c3c..fb1e2746723ac3384c94845b1fe1f4abc362c744 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FormaTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/FormaTypeTestFactory.java
@@ -1,8 +1,8 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import de.xoev.xdomea.FormatType;
 
-class FormaTypeTestFactory {
+public class FormaTypeTestFactory {
 
 	public static FormatType create() {
 		return new FormatType();
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/PrimaerdokumentTypeTestFactory.java
similarity index 83%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/PrimaerdokumentTypeTestFactory.java
index f0ae78aaf77d4af8219bc90e920e504bc53f553b..10ab0639a2dfe6302a3ea5cde212430d3855d717 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/PrimaerdokumentTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/PrimaerdokumentTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import de.xoev.xdomea.PrimaerdokumentType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VersionTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/VersionTypeTestFactory.java
similarity index 80%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VersionTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/VersionTypeTestFactory.java
index b2ee1d70ad1e31e7d6f08e1ff589de41054987e2..66ab10bf99d38d853a0d6ccb6716fcd45ad3d9e0 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VersionTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/file/VersionTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.file;
 
 import de.xoev.xdomea.VersionType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AntragsdatenItemTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AntragsdatenItemTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9d51af847460fcdc73e55073b5caa137021a560
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AntragsdatenItemTypeTestFactory.java
@@ -0,0 +1,44 @@
+package de.ozgcloud.alfa.vorgang;
+
+import de.xoev.xdomea.AntragsdatenGroupType;
+import de.xoev.xdomea.AntragsdatenMultiValueFieldType;
+import de.xoev.xdomea.AntragsdatenSingleValueFieldType;
+import de.xoev.xdomea.AntragsdatenType;
+import de.xoev.xdomea.DatatypeType;
+
+public class AntragsdatenItemTypeTestFactory {
+
+	public static final String KEY_STRING = "string";
+	public static final String KEY_MAP = "map";
+	public static final String KEY_COLLECTION = "collection";
+	public static final String VALUE_STRING = "value1";
+	public static final Integer VALUE_INTEGER = 1;
+
+	public static AntragsdatenSingleValueFieldType createSingleValueField() {
+		var antragsdatenItemType = new AntragsdatenSingleValueFieldType();
+		antragsdatenItemType.setType(DatatypeType.STRING);
+		antragsdatenItemType.setName(KEY_STRING);
+		antragsdatenItemType.setValue(VALUE_STRING);
+		return antragsdatenItemType;
+	}
+
+	public static AntragsdatenMultiValueFieldType createMultiValueField() {
+		var antragsdatenItemType = new AntragsdatenMultiValueFieldType();
+		antragsdatenItemType.setType(DatatypeType.INTEGER);
+		antragsdatenItemType.setName(KEY_COLLECTION);
+		antragsdatenItemType.getValue().add(VALUE_INTEGER);
+		return antragsdatenItemType;
+	}
+
+	public static AntragsdatenGroupType createGroup() {
+		var antragsdatenItemType = new AntragsdatenGroupType();
+		antragsdatenItemType.setName(KEY_MAP);
+
+		var group = new AntragsdatenType();
+		group.getItem().add(createMultiValueField());
+		antragsdatenItemType.setValue(group);
+
+		return antragsdatenItemType;
+	}
+
+}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeCreatorTest.java
similarity index 66%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeCreatorTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeCreatorTest.java
index db766c5063ef4154d736187bad2d8326211b6483..9580936d7e586792190f6a8ca4407b85696b1603 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeCreatorTest.java
@@ -1,7 +1,9 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
@@ -10,10 +12,10 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
+import de.xoev.xdomea.AntragsdatenType;
 import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
 import de.xoev.xdomea.FeldgruppeType;
+import de.xoev.xdomea.OzgcloudErweiterungType;
 
 class AnwendungsspezifischeErweiterungTypeCreatorTest {
 
@@ -23,16 +25,20 @@ class AnwendungsspezifischeErweiterungTypeCreatorTest {
 
 	@Mock
 	private FeldGruppeTypeCreator feldGruppeTypeCreator;
+	@Mock
+	private FormDataMapper formDataMapper;
 
 	@Nested
 	class TestCreate {
 
 		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
 		private final FeldgruppeType feldgruppeType = new FeldgruppeType();
+		private final AntragsdatenType antragsdatenType = new AntragsdatenType();
 
 		@BeforeEach
 		void init() {
 			when(feldGruppeTypeCreator.create(vorgang)).thenReturn(feldgruppeType);
+			when(formDataMapper.toAntragsdatenType(any())).thenReturn(antragsdatenType);
 		}
 
 		@Test
@@ -63,6 +69,20 @@ class AnwendungsspezifischeErweiterungTypeCreatorTest {
 			assertThat(anwendungsspezifischeErweiterung.getFeldgruppe()).hasSize(1).first().isEqualTo(feldgruppeType);
 		}
 
+		@Test
+		void shouldCallFormDataMapper() {
+			create();
+
+			verify(formDataMapper).toAntragsdatenType(vorgang);
+		}
+		
+		@Test
+		void shouldHaveAntragsdaten() {
+			var anwendungsspezifischeErweiterung = (OzgcloudErweiterungType) create();
+			
+			assertThat(anwendungsspezifischeErweiterung.getAntragsdaten()).isNotNull();
+		}
+
 		private AnwendungsspezifischeErweiterungType create() {
 			return creator.create(vorgang);
 		}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeTestFactory.java
similarity index 87%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeTestFactory.java
index 41d1eb74ca6c84d1731057a0e6ee3277c56127e2..c23de6fe41c1d9ff17d9395478793d9830de4280 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AnwendungsspezifischeErweiterungTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/AnwendungsspezifischeErweiterungTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/DatatypeMapperTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/DatatypeMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fc79e9adf1c6d41b455c8baf7679b1c53435b9b
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/DatatypeMapperTest.java
@@ -0,0 +1,89 @@
+package de.ozgcloud.alfa.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.time.LocalDate;
+import java.time.ZonedDateTime;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.InjectMocks;
+
+import de.xoev.xdomea.DatatypeType;
+
+class DatatypeMapperTest {
+
+	@InjectMocks
+	private DatatypeMapper datatypeMapper;
+
+	@DisplayName("should return DatatypeType STRING when")
+	@ParameterizedTest(name = "\"{0}\"")
+	@NullSource
+	@ValueSource(strings = { StringUtils.EMPTY, "a" })
+	void shouldReturnString(String arg) {
+		var datatype = datatypeMapper.from(arg);
+
+		assertThat(datatype).isEqualTo(DatatypeType.STRING);
+	}
+
+	@Test
+	void shouldReturnStringAsDefault() {
+		var datatype = datatypeMapper.from(new Object());
+
+		assertThat(datatype).isEqualTo(DatatypeType.STRING);
+	}
+
+	@Test
+	void shouldReturnDate() {
+		var datatype = datatypeMapper.from(LocalDate.now());
+
+		assertThat(datatype).isEqualTo(DatatypeType.DATE);
+	}
+
+	@Test
+	void shouldReturnDatetime() {
+		var datatype = datatypeMapper.from(ZonedDateTime.now());
+
+		assertThat(datatype).isEqualTo(DatatypeType.DATETIME);
+	}
+
+	@Test
+	void shouldReturnInteger() {
+		var datatype = datatypeMapper.from(1);
+
+		assertThat(datatype).isEqualTo(DatatypeType.INTEGER);
+	}
+
+	@Test
+	void shouldReturnFloat() {
+		var datatype = datatypeMapper.from(1.0f);
+
+		assertThat(datatype).isEqualTo(DatatypeType.FLOAT);
+	}
+
+	@Test
+	void shouldReturnBoolean() {
+		var datatype = datatypeMapper.from(true);
+
+		assertThat(datatype).isEqualTo(DatatypeType.BOOLEAN);
+	}
+
+	@Test
+	void shouldReturnTypeOfElementsInCollection() {
+		var datatype = datatypeMapper.from(List.of(1, 2));
+
+		assertThat(datatype).isEqualTo(DatatypeType.INTEGER);
+	}
+
+	@Test
+	void shouldReturnDefaultIfCollectionIsEmpty() {
+		var datatype = datatypeMapper.from(new Object[] {});
+
+		assertThat(datatype).isEqualTo(DatatypeType.STRING);
+	}
+}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFelderTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportFelderTest.java
similarity index 92%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFelderTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportFelderTest.java
index ace1d7ecd4e1067290a29b8019c8b3e943acfa16..ae5c14a26f56bde7b114c41bcf87b62bcf56ae1d 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFelderTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportFelderTest.java
@@ -1,11 +1,10 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
-import de.ozgcloud.alfa.export.ExportFelder;
 import de.xoev.xdomea.FeldType;
 
 class ExportFelderTest {
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..636005eab233c90dc93f1f0ce352f3b59425adf9
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java
@@ -0,0 +1,94 @@
+package de.ozgcloud.alfa.vorgang;
+
+import static de.ozgcloud.alfa.vorgang.AntragsdatenItemTypeTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ozgcloud.common.test.ITCase;
+import de.xoev.xdomea.AntragsdatenGroupType;
+import de.xoev.xdomea.AntragsdatenItemType;
+import de.xoev.xdomea.AntragsdatenSingleValueFieldType;
+import de.xoev.xdomea.AntragsdatenType;
+import de.xoev.xdomea.OzgcloudErweiterungType;
+
+@ITCase
+class ExportVorgangServiceITCase {
+
+	@Autowired
+	private ExportVorgangService exportVorgangService;
+
+	@Nested
+	class TestMapVorgang {
+
+		@Nested
+		class TestMapAntragsdaten {
+
+			private static final Map<String, Object> FORM_DATA = Map.of(
+					KEY_STRING, VALUE_STRING,
+					KEY_MAP, Map.of(KEY_COLLECTION, List.of(VALUE_INTEGER))
+			);
+
+			@Test
+			void shouldMapSingleField() {
+				var antragsdaten = mapToAntragsdaten();
+
+				assertThat(antragsdaten.getItem()).hasSize(2);
+				assertContainsSingleValueField(antragsdaten.getItem());
+			}
+
+			private void assertContainsSingleValueField(List<AntragsdatenItemType> items) {
+				var singleValueField = items.stream().filter(item -> item instanceof AntragsdatenSingleValueFieldType).findFirst();
+				assertThat(singleValueField).isPresent().get().usingRecursiveComparison().isEqualTo(createSingleValueField());
+			}
+
+			@Test
+			void shouldMapGroup() {
+				var antragsdaten = mapToAntragsdaten();
+
+				assertThat(antragsdaten.getItem()).hasSize(2);
+				assertContainsGroup(antragsdaten.getItem());
+			}
+
+			private void assertContainsGroup(List<AntragsdatenItemType> items) {
+				var group = items.stream().filter(item -> item instanceof AntragsdatenGroupType).findFirst();
+				assertThat(group).isPresent().get().extracting(AntragsdatenItemType::getName).isEqualTo(KEY_MAP);
+			}
+
+			@Test
+			void shouldMapItemsInGroup() {
+				var antragsdaten = mapToAntragsdaten();
+
+				assertThat(antragsdaten.getItem()).hasSize(2);
+				assertContainsItemsInGroup(antragsdaten.getItem());
+			}
+
+			private void assertContainsItemsInGroup(List<AntragsdatenItemType> items) {
+				var groupItem = items.stream().filter(item -> item instanceof AntragsdatenGroupType)
+						.map(item -> ((AntragsdatenGroupType) item))
+						.map(group -> group.getValue().getItem())
+						.flatMap(List::stream).findFirst();
+				assertThat(groupItem).isPresent().get().usingRecursiveComparison().isEqualTo(createMultiValueField());
+
+			}
+
+			private AntragsdatenType mapToAntragsdaten() {
+				var erweiterungType = exportVorgangService.createVorgangType(buildVorgang()).getAnwendungsspezifischeErweiterung();
+
+				assertThat(erweiterungType).isOfAnyClassIn(OzgcloudErweiterungType.class);
+				return ((OzgcloudErweiterungType) erweiterungType).getAntragsdaten();
+			}
+
+			private VorgangWithEingang buildVorgang() {
+				var eingang = EingangTestFactory.createBuilder().formData(FORM_DATA).build();
+				return VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build();
+			}
+
+		}
+	}
+}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9601946a7a579c05ada5c2f21dc6dc73f0b3537d
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java
@@ -0,0 +1,40 @@
+package de.ozgcloud.alfa.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+public class ExportVorgangServiceTest {
+
+	private final static String VORGANG_ID = "DUMMY_ID";
+	private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
+
+	@Spy
+	@InjectMocks
+	private ExportVorgangService exportVorgangService;
+
+	@Mock
+	private VorgangService vorgangService;
+
+	@BeforeEach
+	void init() {
+		when(vorgangService.findVorgangWithEingang(anyString())).thenReturn(vorgang);
+	}
+
+	@Test
+	void shouldCallVorgangService() {
+		exportVorgangService.getVorgang(VORGANG_ID);
+
+		verify(vorgangService).findVorgangWithEingang(VORGANG_ID);
+	}
+
+	@Test
+	void shouldReturnVorgangWithEingang() {
+		assertThat(exportVorgangService.getVorgang(VORGANG_ID)).isEqualTo(vorgang);
+	}
+}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FeldGruppeTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FeldGruppeTypeCreatorTest.java
similarity index 97%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FeldGruppeTypeCreatorTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FeldGruppeTypeCreatorTest.java
index 2ca1494a2bd482efb4d3fd9a3deb931ad8ec1b8b..a78cd333af20803b76a8324e731eba5d760b4e8c 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/FeldGruppeTypeCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FeldGruppeTypeCreatorTest.java
@@ -1,19 +1,14 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
-import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.Spy;
 
-import de.ozgcloud.alfa.vorgang.AntragstellerTestFactory;
-import de.ozgcloud.alfa.vorgang.EingangTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
+import de.ozgcloud.alfa.common.DatentypCode;
 import de.xoev.xdomea.DatentypCodeType;
 import de.xoev.xdomea.FeldType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cfb13a037e85443dc219724cd8821331231f66a
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java
@@ -0,0 +1,274 @@
+package de.ozgcloud.alfa.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZonedDateTime;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+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.alfa.common.DateConverter;
+import de.xoev.xdomea.AntragsdatenFieldType;
+import de.xoev.xdomea.AntragsdatenGroupType;
+import de.xoev.xdomea.AntragsdatenItemType;
+import de.xoev.xdomea.AntragsdatenMultiValueFieldType;
+import de.xoev.xdomea.AntragsdatenSingleValueFieldType;
+import de.xoev.xdomea.DatatypeType;
+import de.xoev.xdomea.ItemListType;
+
+class FormDataMapperTest {
+
+	@Spy
+	@InjectMocks
+	private FormDataMapper formDataMapper;
+
+	@Mock
+	private DatatypeMapper datatypeMapper;
+	@Mock
+	private DateConverter dateConverter;
+
+	@Nested
+	class TestToAntragsdatenType {
+
+		@Mock
+		private VorgangWithEingang vorgang;
+
+		@Test
+		void shouldCallBuildItemType() {
+			doReturn(new Object()).when(formDataMapper).formatValue(any(), any());
+			var vorgang = VorgangWithEingangTestFactory.create();
+
+			formDataMapper.toAntragsdatenType(vorgang);
+
+			verify(formDataMapper).buileItemListType(vorgang.getEingang().getFormData());
+		}
+
+		@Test
+		void shouldMapEingangNull() {
+			var antragsdatenType = formDataMapper.toAntragsdatenType(vorgang);
+
+			assertThat(antragsdatenType.getItem()).isEmpty();
+		}
+
+		@Test
+		void shouldMapFormDataNull() {
+			var eingang = mock(Eingang.class);
+			when(vorgang.getEingang()).thenReturn(eingang);
+
+			var antragsdatenType = formDataMapper.toAntragsdatenType(vorgang);
+
+			assertThat(antragsdatenType.getItem()).isEmpty();
+		}
+
+	}
+
+	@Nested
+	class TestBuildItemListType {
+
+		@Mock
+		private AntragsdatenItemType antragsdatenItemType1;
+		@Mock
+		private AntragsdatenItemType antragsdatenItemType2;
+
+		@Test
+		void shouldAddItems() {
+			doReturn(List.of(antragsdatenItemType1, antragsdatenItemType2)).when(formDataMapper).buildItems(any());
+
+			var itemListType = formDataMapper.buileItemListType(EingangTestFactory.AS_MAP);
+
+			assertThat(itemListType.getItem()).containsExactly(antragsdatenItemType1, antragsdatenItemType2);
+		}
+	}
+
+	@Nested
+	class TestBuildItems {
+		@Mock
+		private AntragsdatenItemType expectedAntragsdatenItem;
+
+		@Test
+		void shouldReturnEmptyList() {
+			var items = formDataMapper.buildItems(Collections.emptyMap());
+
+			assertThat(items).isEmpty();
+		}
+
+		@Test
+		void shoulAddSubmap() {
+			doReturn(expectedAntragsdatenItem).when(formDataMapper).buildAntragsdatenGroup(any(), any());
+
+			var items = formDataMapper.buildItems(Map.of("key", Map.of("key", "value")));
+
+			assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem);
+		}
+
+		@Test
+		void shouldAddCollection() {
+			doReturn(expectedAntragsdatenItem).when(formDataMapper).buildMultiValueField(any(), any());
+
+			var items = formDataMapper.buildItems(Map.of("key", List.of("value")));
+
+			assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem);
+		}
+
+		@Test
+		void shouldAddSingleValue() {
+			doReturn(expectedAntragsdatenItem).when(formDataMapper).buildSingleValueField(any(), any());
+
+			var items = formDataMapper.buildItems(Map.of("key", "value"));
+
+			assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem);
+		}
+	}
+
+	@Nested
+	class TestBuildAntragsdatenGroup {
+
+		private static final String NAME = "name";
+		private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key", "value");
+
+		@Mock
+		private ItemListType itemListType;
+
+		@Test
+		void shouldSetName() {
+			doReturn(new Object()).when(formDataMapper).formatValue(any(), any());
+
+			var antragsdatenGroup = formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP);
+
+			assertThat(antragsdatenGroup.getName()).isEqualTo(NAME);
+		}
+
+		@Test
+		void shouldSetValue() {
+			doReturn(itemListType).when(formDataMapper).buileItemListType(any());
+
+			var antragsdatenGroup = (AntragsdatenGroupType) formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP);
+
+			assertThat(antragsdatenGroup.getValue()).isEqualTo(itemListType);
+		}
+
+		@Test
+		void shouldCallBuildItemListType() {
+			doReturn(new Object()).when(formDataMapper).formatValue(any(), any());
+
+			formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP);
+
+			verify(formDataMapper).buileItemListType(FORMDATA_SUBMAP);
+		}
+	}
+
+	@Nested
+	class TestBuildMultiValueField {
+
+		private static final String NAME = "name";
+		private static final List<String> FORMDATA_COLLECTION = List.of("value1");
+
+		@Test
+		void shouldSetName() {
+			when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING);
+
+			var antragsdatenMultiValueFieldType = formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION);
+
+			assertThat(antragsdatenMultiValueFieldType.getName()).isEqualTo(NAME);
+		}
+
+		@Test
+		void shouldSetType() {
+			when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING);
+
+			var antragsdatenMultiValueFieldType = (AntragsdatenFieldType) formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION);
+
+			assertThat(antragsdatenMultiValueFieldType.getType()).isEqualTo(DatatypeType.STRING);
+		}
+
+		@Test
+		void shouldSetValue() {
+			when(datatypeMapper.from(any())).thenReturn(DatatypeType.INTEGER);
+			var formData = List.of(1, 2);
+
+			var antragsdatenMultiValueFieldType = (AntragsdatenMultiValueFieldType) formDataMapper.buildMultiValueField(NAME, formData);
+
+			assertThat(antragsdatenMultiValueFieldType.getValue()).containsExactlyElementsOf(formData);
+		}
+
+		@Test
+		void shouldCallFormatValue() {
+			when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING);
+
+			formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION);
+
+			verify(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_COLLECTION.get(0));
+		}
+	}
+
+	@Nested
+	class TestBuildSingleValueField {
+
+		private static final String NAME = "name";
+		private static final String FORMDATA_VALUE = "value";
+
+		@Test
+		void shouldSetName() {
+			doReturn(new Object()).when(formDataMapper).formatValue(any(), any());
+
+			var antragsdatenSingleValueFieldType = formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE);
+
+			assertThat(antragsdatenSingleValueFieldType.getName()).isEqualTo(NAME);
+		}
+
+		@Test
+		void shouldSetType() {
+			when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING);
+
+			var antragsdatenSingleValueFieldType = (AntragsdatenFieldType) formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE);
+
+			assertThat(antragsdatenSingleValueFieldType.getType()).isEqualTo(DatatypeType.STRING);
+		}
+
+		@Test
+		void shouldSetValue() {
+			doReturn(FORMDATA_VALUE).when(formDataMapper).formatValue(any(), any());
+
+			var antragsdatenSingleValueFieldType = (AntragsdatenSingleValueFieldType) formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE);
+
+			assertThat(antragsdatenSingleValueFieldType.getValue()).isEqualTo(FORMDATA_VALUE);
+		}
+
+		@Test
+		void shouldCallFormatValue() {
+			when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING);
+
+			formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE);
+
+			verify(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_VALUE);
+		}
+	}
+
+	@Nested
+	class TestFormatValue {
+
+		@Test
+		void shouldFormatStringType() {
+			var value = formDataMapper.formatValue(DatatypeType.STRING, 1);
+
+			assertThat(value).isEqualTo("1");
+		}
+
+		@Test
+		void shouldFormatDateTimeType() {
+			var dateTime = ZonedDateTime.now();
+
+			formDataMapper.formatValue(DatatypeType.DATETIME, dateTime);
+
+			verify(dateConverter).toXmlGregorianCalendar(dateTime);
+		}
+	}
+}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/GeburtTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/GeburtTypeTestFactory.java
similarity index 80%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/GeburtTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/GeburtTypeTestFactory.java
index 34c8fef41b03a4f5c1c31c51a0c23735f1d61522..1eff8f3fd7bca104f131c92d107fdebe1ed16b12 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/GeburtTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/GeburtTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import de.xoev.xdomea.GeburtType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/KontaktTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KontaktTypeCreatorTest.java
similarity index 76%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/KontaktTypeCreatorTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KontaktTypeCreatorTest.java
index e9a7d11824af1db52a8e6c21031f132194149b68..c232ce356b7fd6f9ee86d0ad17b05cf7d3349e4b 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/KontaktTypeCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KontaktTypeCreatorTest.java
@@ -1,7 +1,6 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
 
 import java.util.Optional;
 
@@ -12,13 +11,10 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.Spy;
 
-import de.ozgcloud.alfa.vorgang.Antragsteller;
-import de.ozgcloud.alfa.vorgang.AntragstellerTestFactory;
-import de.ozgcloud.alfa.vorgang.EingangTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
+import de.ozgcloud.alfa.common.DateConverter;
 import de.xoev.xdomea.GeburtType;
 import de.xoev.xdomea.KontaktType;
 import de.xoev.xdomea.NameNatuerlichePersonType;
@@ -46,22 +42,22 @@ class KontaktTypeCreatorTest {
 
 			@BeforeEach
 			void setUp() {
-				doReturn(Optional.of(vorgang.getEingang().getAntragsteller())).when(creator).getAntragstellerIfHasRequiredData(vorgang);
-				doReturn(kontaktType).when(creator).toKontaktType(vorgang.getEingang().getAntragsteller());
+				Mockito.doReturn(Optional.of(vorgang.getEingang().getAntragsteller())).when(creator).getAntragstellerIfHasRequiredData(vorgang);
+				Mockito.doReturn(kontaktType).when(creator).toKontaktType(vorgang.getEingang().getAntragsteller());
 			}
 
 			@Test
 			void shouldGetAntragsteller() {
 				callCreator(vorgang);
 
-				verify(creator).getAntragstellerIfHasRequiredData(vorgang);
+				Mockito.verify(creator).getAntragstellerIfHasRequiredData(vorgang);
 			}
 
 			@Test
 			void shouldMapToKontaktType() {
 				callCreator(vorgang);
 
-				verify(creator).toKontaktType(vorgang.getEingang().getAntragsteller());
+				Mockito.verify(creator).toKontaktType(vorgang.getEingang().getAntragsteller());
 			}
 
 			@Test
@@ -81,7 +77,7 @@ class KontaktTypeCreatorTest {
 
 			@BeforeEach
 			void setUp() {
-				doReturn(Optional.empty()).when(creator).getAntragstellerIfHasRequiredData(vorgang);
+				Mockito.doReturn(Optional.empty()).when(creator).getAntragstellerIfHasRequiredData(vorgang);
 			}
 
 			@Test
@@ -109,16 +105,16 @@ class KontaktTypeCreatorTest {
 
 		@BeforeEach
 		void setUp() {
-			when(nameNatuerlichePersonTypeCreator.create(vorgang.getEingang().getAntragsteller())).thenReturn(nameNatuerlichePerson);
-			when(dateConverter.convertGermanFormatToISO(AntragstellerTestFactory.GEBURTSDATUM_STR)).thenReturn(Optional.of(geburtsdatum));
-			doReturn(geburtType).when(creator).createGeburtType(Optional.of(geburtsdatum));
+			Mockito.when(nameNatuerlichePersonTypeCreator.create(vorgang.getEingang().getAntragsteller())).thenReturn(nameNatuerlichePerson);
+			Mockito.when(dateConverter.convertGermanFormatToISO(AntragstellerTestFactory.GEBURTSDATUM_STR)).thenReturn(Optional.of(geburtsdatum));
+			Mockito.doReturn(geburtType).when(creator).createGeburtType(Optional.of(geburtsdatum));
 		}
 
 		@Test
 		void shouldCreateNameNatuerlichePerson() {
 			callCreator(vorgang);
 
-			verify(nameNatuerlichePersonTypeCreator).create(vorgang.getEingang().getAntragsteller());
+			Mockito.verify(nameNatuerlichePersonTypeCreator).create(vorgang.getEingang().getAntragsteller());
 		}
 
 		@Test
@@ -132,14 +128,14 @@ class KontaktTypeCreatorTest {
 		void shouldCallDateConverter() {
 			callCreator(vorgang);
 
-			verify(dateConverter).convertGermanFormatToISO(AntragstellerTestFactory.GEBURTSDATUM_STR);
+			Mockito.verify(dateConverter).convertGermanFormatToISO(AntragstellerTestFactory.GEBURTSDATUM_STR);
 		}
 
 		@Test
 		void shouldCreateGeburtType() {
 			callCreator(vorgang);
 
-			verify(creator).createGeburtType(Optional.of(geburtsdatum));
+			Mockito.verify(creator).createGeburtType(Optional.of(geburtsdatum));
 		}
 
 		@Test
@@ -194,7 +190,7 @@ class KontaktTypeCreatorTest {
 
 		@Test
 		void shouldBeEmptyIfNoneOfRequiredDataExists() {
-			when(dateConverter.convertGermanFormatToISO(null)).thenReturn(Optional.empty());
+			Mockito.when(dateConverter.convertGermanFormatToISO(null)).thenReturn(Optional.empty());
 
 			var antragsteller = callCreator(buildVorgang(Antragsteller.builder().build()));
 
@@ -224,7 +220,7 @@ class KontaktTypeCreatorTest {
 
 		@Test
 		void shouldNotBeEmptyIfHasGeburtsdatum() {
-			when(dateConverter.convertGermanFormatToISO(AntragstellerTestFactory.GEBURTSDATUM_STR)).thenReturn(Optional.of(geburtsdatum));
+			Mockito.when(dateConverter.convertGermanFormatToISO(AntragstellerTestFactory.GEBURTSDATUM_STR)).thenReturn(Optional.of(geburtsdatum));
 
 			var antragsteller = callCreator(buildVorgang(Antragsteller.builder().geburtsdatum(AntragstellerTestFactory.GEBURTSDATUM_STR).build()));
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/KontaktTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KontaktTypeTestFactory.java
similarity index 81%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/KontaktTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KontaktTypeTestFactory.java
index 3daad690a0d408df23c9e0b75dbee73720a128cd..964eb818e77f28b7fb396c3a4d1d33d0937c418f 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/KontaktTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KontaktTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import de.xoev.xdomea.KontaktType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fab8514b0e509308e40b725fcab69545433c904b
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java
@@ -0,0 +1,251 @@
+package de.ozgcloud.alfa.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+
+import de.ozgcloud.alfa.common.DateConverter;
+import de.ozgcloud.alfa.export.XDomeaProperties;
+import de.xoev.xdomea.BehoerdenkennungType;
+import de.xoev.xdomea.Code;
+import de.xoev.xdomea.KontaktType;
+import de.xoev.xdomea.NachrichtentypCodeType;
+import de.xoev.xdomea.NkAbgabeType;
+import de.xoev.xdomea.OrganisationseinheitType;
+import de.xoev.xdomea.SystemType;
+
+class KopfCreatorTest {
+
+	@Spy
+	@InjectMocks
+	private KopfCreator creator;
+
+	@Mock
+	private XDomeaProperties xDomeaProperties;
+	@Mock
+	private DateConverter dateConverter;
+
+	@Nested
+	class TestCreateKopf {
+
+		static final ZonedDateTime CREATION_TIME = ZonedDateTime.now();
+
+		@Test
+		void shouldSetProcessId() {
+			var kopf = createKopf();
+
+			assertThat(kopf.getProzessID()).isEqualTo(VorgangHeaderTestFactory.ID);
+		}
+
+		@Test
+		void shouldSetNachrichtentyp() {
+			var expectedValue = new NachrichtentypCodeType();
+			doReturn(expectedValue).when(creator).createNachrichtentyp();
+
+			var kopf = createKopf();
+
+			assertThat(kopf.getNachrichtentyp()).isEqualTo(expectedValue);
+		}
+
+		@Test
+		void shouldSetErstellungszeitpunkt() {
+			try (var zonedDateTime = Mockito.mockStatic(ZonedDateTime.class)) {
+				zonedDateTime.when(() -> ZonedDateTime.now(ZoneOffset.UTC)).thenReturn(CREATION_TIME);
+
+				var expectedValue = mock(XMLGregorianCalendar.class);
+				when(dateConverter.toXmlGregorianCalendar(CREATION_TIME)).thenReturn(expectedValue);
+
+				var kopf = createKopf();
+
+				assertThat(kopf.getErstellungszeitpunkt()).isEqualTo(expectedValue);
+			}
+		}
+
+		@Test
+		void shouldSetAbsender() {
+			var expectedValue = new KontaktType();
+			doReturn(expectedValue).when(creator).createAbsender(any());
+
+			var kopf = createKopf();
+
+			assertThat(kopf.getAbsender()).isEqualTo(expectedValue);
+		}
+
+		@Test
+		void shouldSetEmpfaenger() {
+			var expectedValue = new KontaktType();
+			doReturn(expectedValue).when(creator).createKontaktType();
+
+			var kopf = createKopf();
+
+			assertThat(kopf.getEmpfaenger()).isEqualTo(expectedValue);
+		}
+
+		@Test
+		void shouldSetSendendesSystem() {
+			var sendendesSystem = new SystemType();
+			doReturn(sendendesSystem).when(creator).creeateSendendesSystem();
+
+			var kopf = createKopf();
+
+			assertThat(kopf.getSendendesSystem()).isEqualTo(sendendesSystem);
+		}
+
+		@Test
+		void shouldSetImportbestaetigung() {
+			var kopf = createKopf();
+
+			assertThat(kopf.isImportbestaetigung()).isTrue();
+		}
+
+		@Test
+		void shouldSetEmpfangsbestaetigung() {
+			var kopf = createKopf();
+
+			assertThat(kopf.isEmpfangsbestaetigung()).isTrue();
+		}
+
+		private NkAbgabeType createKopf() {
+			return creator.createKopf(VorgangWithEingangTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestCreateNachrichtentype {
+
+		@Test
+		void shouldSetCode() {
+			var nachrichtentyp = creator.createNachrichtentyp();
+
+			assertThat(nachrichtentyp.getCode()).isEqualTo(KopfCreator.NACHRICHTENTYP_ABGABE_ABGABE_TYPE_CODE);
+		}
+
+		@Test
+		void shouldSetListURI() {
+			var nachrichtentyp = creator.createNachrichtentyp();
+
+			assertThat(nachrichtentyp.getListURI()).isEqualTo(KopfCreator.NACHRICHTENTYP_CODE_TYPE_LIST_URI);
+		}
+
+		@Test
+		void shouldSetListVersionID() {
+			var nachrichtentyp = creator.createNachrichtentyp();
+
+			assertThat(nachrichtentyp.getListVersionID()).isEqualTo(KopfCreator.NACHRICHTENTYP_CODE_TYPE_LIST_VERSION_ID);
+		}
+	}
+
+	@Nested
+	class TestCreateAbsender {
+
+		@Mock
+		private BehoerdenkennungType behoerdenkennungType;
+
+		@Test
+		void shouldCallCreateKontaktType() {
+			creator.createAbsender(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
+
+			verify(creator).createKontaktType();
+		}
+
+		@Test
+		void shouldSetOrganisationseinheitType() {
+			var expectedValue = new OrganisationseinheitType();
+			doReturn(expectedValue).when(creator).createOrganisationseinheitType(any());
+
+			var absender = creator.createAbsender(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
+
+			assertThat(absender.getOrganisationseinheit()).isEqualTo(expectedValue);
+		}
+	}
+
+	@Nested
+	class TestCreateKontaktType {
+
+		@Test
+		void shouldSetBehoerdenkennungType() {
+			var expectedValue = new BehoerdenkennungType();
+			doReturn(expectedValue).when(creator).createBehoerdenkennung();
+
+			var kontaktType = creator.createAbsender(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
+
+			assertThat(kontaktType.getBehoerdenkennung()).isEqualTo(expectedValue);
+
+		}
+	}
+
+	@Nested
+	class TestCreateOrganisationseinheitType {
+
+		@Test
+		void shouldSetName() {
+			var organisationseinheitType = creator.createOrganisationseinheitType(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
+
+			assertThat(organisationseinheitType.getName()).isEqualTo(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
+		}
+	}
+
+	@Nested
+	class TestCreateBehoerdenkennung {
+
+		@Test
+		void shouldSetBehoerdenschluessel() {
+			var expectedBehoerdenschluessel = new Code();
+			doReturn(expectedBehoerdenschluessel).when(creator).createBehoerdenschlussen();
+
+			var behoerdenkennungType = creator.createBehoerdenkennung();
+
+			assertThat(behoerdenkennungType.getBehoerdenschluessel()).isEqualTo(expectedBehoerdenschluessel);
+		}
+	}
+
+	@Nested
+	class TestCreateBehoerdenschlussel {
+
+		@Test
+		void shouldSetCode() {
+			var expectedBehoerdenschluessel = "123456789";
+			when(xDomeaProperties.getBehoerdenschluessel()).thenReturn(expectedBehoerdenschluessel);
+
+			var behoerdenschlussel = creator.createBehoerdenschlussen();
+
+			assertThat(behoerdenschlussel.getCode()).isEqualTo(expectedBehoerdenschluessel);
+		}
+
+		@Test
+		void shouldSetListURI() {
+			var behoerdenschlussel = creator.createBehoerdenschlussen();
+
+			assertThat(behoerdenschlussel.getListURI()).isEqualTo(KopfCreator.BEHOERDENSCHLUSSEL_LIST_URI);
+		}
+
+		@Test
+		void shouldSetListVersionID() {
+			var behoerdenschlussel = creator.createBehoerdenschlussen();
+
+			assertThat(behoerdenschlussel.getListVersionID()).isEqualTo(KopfCreator.BEHOERDENSCHLUSSEL_LIST_VERSION_ID);
+		}
+	}
+
+	@Nested
+	class TestCreateSendendesSystem {
+
+		@Test
+		void shouldSetSystemName() {
+			var sendendesSystem = creator.creeateSendendesSystem();
+
+			assertThat(sendendesSystem.getProduktname()).isEqualTo(KopfCreator.PRODUKT_NAME);
+		}
+	}
+}
\ No newline at end of file
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeCreatorTest.java
similarity index 94%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeCreatorTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeCreatorTest.java
index 7124b6f846a1cd545df3a71c4567f2f42c166f70..04bed62960387ee3ebef07bcc2cc59156371547d 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeCreatorTest.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -6,8 +6,6 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 
-import de.ozgcloud.alfa.vorgang.Antragsteller;
-import de.ozgcloud.alfa.vorgang.AntragstellerTestFactory;
 import de.xoev.xdomea.NameNatuerlichePersonType;
 
 class NameNatuerlichePersonTypeCreatorTest {
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeTestFactory.java
similarity index 85%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeTestFactory.java
index 79abd234311aa7c864b7b146f932aa9197c5d980..09b861eca1903f844baf2075c85fd3f9b01219ae 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/NameNatuerlichePersonTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/NameNatuerlichePersonTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import de.xoev.xdomea.NameNatuerlichePersonType;
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VorgangTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java
similarity index 85%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VorgangTypeCreatorTest.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java
index f97c9906d1eaa1c8cfe8414b2b574c95983e8c5b..718b296b0c7cfc33ea5221a628d042df0c7e55d2 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VorgangTypeCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java
@@ -1,10 +1,9 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Optional;
-import java.util.stream.Stream;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
@@ -14,12 +13,10 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 
 import de.ozgcloud.alfa.common.TestUtils;
-import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
-import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
+import de.ozgcloud.alfa.export.AllgemeineMetadatenTypeTestFactory;
+import de.ozgcloud.alfa.export.IdentifikationObjektTypeTestFactory;
 import de.xoev.xdomea.AllgemeineMetadatenType;
 import de.xoev.xdomea.AnwendungsspezifischeErweiterungType;
-import de.xoev.xdomea.DokumentType;
 import de.xoev.xdomea.IdentifikationObjektType;
 import de.xoev.xdomea.KontaktType;
 import de.xoev.xdomea.VorgangType;
@@ -31,7 +28,7 @@ class VorgangTypeCreatorTest {
 	private VorgangTypeCreator creator;
 
 	@Mock
-	private DokumentTypeCreator dokumentTypeCreator;
+	private AnwendungsspezifischeErweiterungTypeCreator anwendungsspezifischeErweiterungTypeCreator;
 
 	@Mock
 	private KontaktTypeCreator kontaktTypeCreator;
@@ -44,7 +41,6 @@ class VorgangTypeCreatorTest {
 		private final IdentifikationObjektType identifikationObjekt = IdentifikationObjektTypeTestFactory.create();
 		private final AllgemeineMetadatenType allgemeineMetadaten = AllgemeineMetadatenTypeTestFactory.create();
 		private final AnwendungsspezifischeErweiterungType anwendungsspezifischeErweiterung = AnwendungsspezifischeErweiterungTypeTestFactory.create();
-		private final DokumentType dokument = DokumentTypeTestFactory.create();
 		private final KontaktType kontakt = KontaktTypeTestFactory.create();
 
 		@BeforeEach
@@ -52,10 +48,17 @@ class VorgangTypeCreatorTest {
 			doReturn(identifikationObjekt).when(creator).createIdentifikation();
 			doReturn(allgemeineMetadaten).when(creator).createAllgemeineMetadaten(vorgang);
 
-			when(dokumentTypeCreator.create(vorgang)).thenReturn(Stream.of(dokument));
+			when(anwendungsspezifischeErweiterungTypeCreator.create(vorgang)).thenReturn(anwendungsspezifischeErweiterung);
 			when(kontaktTypeCreator.create(vorgang)).thenReturn(Optional.of(kontakt));
 		}
 
+		@Test
+		void shouldCallAnwendungsspezifischeErweiterungTypeCreator() {
+			callCreator();
+
+			verify(anwendungsspezifischeErweiterungTypeCreator).create(vorgang);
+		}
+
 		@Test
 		void shouldHaveAnwendungsspezifischeErweiterungType() {
 			var vorgangType = callCreator();
@@ -91,14 +94,6 @@ class VorgangTypeCreatorTest {
 			assertThat(vorgangType.getAllgemeineMetadaten()).isEqualTo(allgemeineMetadaten);
 		}
 
-		@Test
-		void shouldCreateDokumenType() {
-			var vorgangType = callCreator();
-
-			verify(dokumentTypeCreator).create(vorgang);
-			assertThat(vorgangType.getDokument()).hasSize(1).containsExactly(dokument);
-		}
-
 		@Test
 		void shouldCallKontaktTypeCreator() {
 			callCreator();
@@ -122,7 +117,7 @@ class VorgangTypeCreatorTest {
 		}
 
 		private VorgangType callCreator() {
-			return creator.create(vorgang, anwendungsspezifischeErweiterung);
+			return creator.create(vorgang);
 		}
 	}
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VorgangTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeTestFactory.java
similarity index 81%
rename from alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VorgangTypeTestFactory.java
rename to alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeTestFactory.java
index 8749f09b5bafb1ff17ee2884679aaf4cb3ff1e54..45ca4e476144809edd9e1b2a064a884bef92d68d 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/VorgangTypeTestFactory.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.alfa.export;
+package de.ozgcloud.alfa.vorgang;
 
 import de.xoev.xdomea.VorgangType;