Skip to content
Snippets Groups Projects
Commit ee5a9e25 authored by OZGCloud's avatar OZGCloud
Browse files

Merge pull request 'OZG-6162-archive-manager-anbindung' (#820) from...

Merge pull request 'OZG-6162-archive-manager-anbindung' (#820) from OZG-6162-archive-manager-anbindung into master

Reviewed-on: https://git.ozg-sh.de/ozgcloud-app/alfa/pulls/820


Reviewed-by: default avatarOZGCloud <ozgcloud@mgm-tp.com>
parents a3aa7b84 5b597ce7
Branches
Tags
No related merge requests found
Showing
with 0 additions and 1008 deletions
package de.ozgcloud.alfa.bescheid;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import de.ozgcloud.alfa.common.AnlageDokumentTypeBuilder;
import de.ozgcloud.alfa.common.DateConverter;
import de.ozgcloud.alfa.common.IdentifikationObjektTypeBuilder;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.xoev.xdomea.AllgemeineMetadatenType;
import de.xoev.xdomea.AnlageDokumentType;
import de.xoev.xdomea.DokumentType;
import de.xoev.xdomea.HistorienProtokollInformationType;
class DokumentTypeBuilder {
private static final String TYP = "Bescheid";
private static final Map<Boolean, String> BEMERKUNG = Map.of(true, "Bescheid wurde genehmigt.", false, "Bescheid wurde abgelehnt.");
private static final Map<SendBy, String> AKTION = Map.of(SendBy.MANUAL, "Bescheid gespeichert", SendBy.NACHRICHT,
"Bescheid an Antragsteller gesendet");
private Bescheid bescheid;
private String organisationsEinheitenId;
private String fullName;
private List<OzgFile> files;
public static DokumentTypeBuilder builder() {
return new DokumentTypeBuilder();
}
public DokumentTypeBuilder withBescheid(Bescheid bescheid) {
this.bescheid = bescheid;
return this;
}
public DokumentTypeBuilder withOrganisationseinheitenId(String organisationsEinheitenId) {
this.organisationsEinheitenId = organisationsEinheitenId;
return this;
}
public DokumentTypeBuilder withFullName(String fullName) {
this.fullName = fullName;
return this;
}
public DokumentTypeBuilder withFiles(List<OzgFile> files) {
this.files = files;
return this;
}
public DokumentType build() {
var dokumentType = new DokumentType();
dokumentType.setIdentifikation(IdentifikationObjektTypeBuilder.builder().withObjectID(bescheid.getId()).build());
dokumentType.setTyp(TYP);
dokumentType.setBezug(StringUtils.defaultString(bescheid.getNachrichtSubject()));
dokumentType.setAllgemeineMetadaten(createAllgemeineMetadaten());
dokumentType.getHistorienProtokollInformation().add(createHistorienProtokollInformation());
Optional.ofNullable(files).orElseGet(Collections::emptyList).stream().map(this::createAnlage).forEach(dokumentType.getAnlage()::add);
return dokumentType;
}
AllgemeineMetadatenType createAllgemeineMetadaten() {
var metadaten = new AllgemeineMetadatenType();
metadaten.setBemerkung(BEMERKUNG.get(bescheid.getBewilligt()));
return metadaten;
}
HistorienProtokollInformationType createHistorienProtokollInformation() {
var protokollInfo = new HistorienProtokollInformationType();
protokollInfo.setMetadatumName(StringUtils.defaultString(bescheid.getNachrichtText()));
protokollInfo.setAkteur(fullName + "; " + organisationsEinheitenId);
protokollInfo.setDatumUhrzeit(DateConverter.toXmlGregorianCalendar(bescheid.getSentInfo().getSentAt()));
protokollInfo.setAktion(AKTION.get(bescheid.getSendBy()));
return protokollInfo;
}
AnlageDokumentType createAnlage(OzgFile ozgFile) {
return AnlageDokumentTypeBuilder.builder().withOzgFile(ozgFile).build();
}
}
package de.ozgcloud.alfa.bescheid;
import java.util.stream.Stream;
import org.springframework.stereotype.Service;
import de.ozgcloud.alfa.common.binaryfile.BinaryFileService;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.ozgcloud.alfa.common.user.UserService;
import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
import de.xoev.xdomea.DokumentType;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class ExportBescheidService {
private final BescheidService bescheidService;
private final BinaryFileService binaryFileService;
private final DocumentService documentService;
private final UserService userService;
public BescheidExportData createExportData(VorgangWithEingang vorgang) {
var builder = BescheidExportData.builder();
getBescheids(vorgang.getId())
.forEach(bescheid -> addBescheidExportData(createBescheidExportInput(bescheid, vorgang), builder));
return builder.build();
}
Stream<Bescheid> getBescheids(String vorgangId) {
return bescheidService.findByVorgangIdSorted(vorgangId).filter(bescheid -> BescheidStatus.SENT == bescheid.getStatus());
}
BescheidExportInput createBescheidExportInput(Bescheid bescheid, VorgangWithEingang vorgang) {
return BescheidExportInput.builder()
.bescheid(bescheid)
.organisationseinheitenId(vorgang.getOrganisationseinheitenID())
.files(Stream.concat(Stream.of(getDocument(bescheid)), getAttachments(bescheid)).toList()).build();
}
Stream<OzgFile> getAttachments(Bescheid bescheid) {
return binaryFileService.getFiles(bescheid.getAttachments());
}
void addBescheidExportData(BescheidExportInput input, BescheidExportData.BescheidExportDataBuilder builder) {
builder.dokumentType(buildDokumentType(input))
.files(input.files());
}
OzgFile getDocument(Bescheid bescheid) {
var document = documentService.getDocument(bescheid.getBescheidDocument());
return binaryFileService.getFile(document.getFileId());
}
DokumentType buildDokumentType(BescheidExportInput input) {
var builder = DokumentTypeBuilder.builder();
builder.withBescheid(input.bescheid())
.withFiles(input.files())
.withFullName(getFullName(input.bescheid()))
.withOrganisationseinheitenId(input.organisationseinheitenId());
return builder.build();
}
String getFullName(Bescheid bescheid) {
return userService.getById(bescheid.getSentInfo().getSentBy()).getFullName();
}
}
package de.ozgcloud.alfa.common;
import java.time.ZonedDateTime;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.xoev.xdomea.AnlageDokumentType;
public class AnlageDokumentTypeBuilder {
private OzgFile ozgFile;
private ZonedDateTime createdAt;
public static AnlageDokumentTypeBuilder builder() {
return new AnlageDokumentTypeBuilder();
}
public AnlageDokumentTypeBuilder withOzgFile(OzgFile ozgFile) {
this.ozgFile = ozgFile;
return this;
}
public AnlageDokumentTypeBuilder withCreatedAt(ZonedDateTime createdAt) {
this.createdAt = createdAt;
return this;
}
public AnlageDokumentType build() {
var anlage = new AnlageDokumentType();
anlage.setIdentifikation(IdentifikationObjektTypeBuilder.builder()
.withObjectID(ozgFile.getId().toString())
.build());
anlage.getVersion().add(VersionTypeBuilder.builder()
.withCreatedAt(createdAt)
.withOzgFile(ozgFile).build());
return anlage;
}
}
package de.ozgcloud.alfa.common;
import static java.util.Objects.*;
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 de.ozgcloud.common.errorhandling.TechnicalException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DateConverter {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMAN);
public static Optional<XMLGregorianCalendar> convertGermanFormatToISO(String dateStr) {
try {
if (nonNull(dateStr)) {
return Optional.of(createDatatypeFactory().newXMLGregorianCalendar(LocalDate.parse(dateStr, DATE_TIME_FORMATTER).toString()));
}
} catch (Exception e) {
LOG.warn("Date '{}' cannot be converted to ISO format.", dateStr, e);
}
return Optional.empty();
}
public static XMLGregorianCalendar toXmlGregorianCalendar(ZonedDateTime date) {
try {
if (nonNull(date)) {
return createDatatypeFactory().newXMLGregorianCalendar(GregorianCalendar.from(date));
}
} catch (Exception e) {
LOG.warn("Date '{}' cannot be converted to ISO format.", date, e);
}
return null;
}
public static XMLGregorianCalendar createEmpty() {
return DateConverter.createDatatypeFactory().newXMLGregorianCalendar();
}
static DatatypeFactory createDatatypeFactory() {
try {
return DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e) {
throw new TechnicalException("Error creating datatype factory.", e);
}
}
}
package de.ozgcloud.alfa.common;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DateiformatCode {
static final String SONSTIGES_CODE = "100";
// MIME type -> file extension -> xdomea code
private static final Map<String, Map<String, String>> mimeTypesMapping = new HashMap<>();
static {
mimeTypesMapping.put("image/bmp", Map.of("bmp", "001"));
mimeTypesMapping.put("text/csv", Map.of("csv", "002"));
mimeTypesMapping.put("application/msword", Map.of("doc", "003", "dot", "032"));
mimeTypesMapping.put("message/rfc822", Map.of("eml", "006"));
mimeTypesMapping.put("text/html", Map.of("htm", "007", "html", "008"));
mimeTypesMapping.put("image/jpeg", Map.of("jpe", "009", "jpeg", "010", "jpg", "011"));
mimeTypesMapping.put("application/vnd.ms-outlook", Map.of("msg", "012"));
mimeTypesMapping.put("application/vnd.oasis.opendocument.presentation", Map.of("odp", "013"));
mimeTypesMapping.put("application/vnd.oasis.opendocument.spreadsheet", Map.of("ods", "014"));
mimeTypesMapping.put("application/vnd.oasis.opendocument.text", Map.of("odt", "015"));
mimeTypesMapping.put("application/vnd.oasis.opendocument.presentation-template", Map.of("otp", "016"));
mimeTypesMapping.put("application/vnd.oasis.opendocument.spreadsheet-template", Map.of("ots", "017"));
mimeTypesMapping.put("application/pdf", Map.of("pdf", "018"));
mimeTypesMapping.put("image/png", Map.of("png", "019"));
mimeTypesMapping.put("application/vnd.ms-powerpoint", Map.of("ppt", "020", "pot", "033"));
mimeTypesMapping.put("application/postscript", Map.of("ps", "021"));
mimeTypesMapping.put("application/rtf", Map.of("rtf", "022"));
mimeTypesMapping.put("image/tiff", Map.of("tif", "023", "tiff", "024"));
mimeTypesMapping.put("application/vnd.ms-works", Map.of("wps", "025"));
mimeTypesMapping.put("application/vnd.ms-excel", Map.of("xlc", "026", "xlm", "027", "xls", "028", "xlw", "029", "xlt", "034"));
mimeTypesMapping.put("application/xml", Map.of("xml", "030", "xsd", "031"));
mimeTypesMapping.put("text/xml", Map.of("xml", "030", "xsd", "031"));
mimeTypesMapping.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", Map.of("docx", "035"));
mimeTypesMapping.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Map.of("xlsx", "036"));
mimeTypesMapping.put("application/vnd.openxmlformats-officedocument.presentationml.presentation", Map.of("pptx", "037"));
mimeTypesMapping.put("application/vnd.openxmlformats-officedocument.wordprocessingml.template", Map.of("dotx", "038"));
mimeTypesMapping.put("application/vnd.openxmlformats-officedocument.spreadsheetml.template", Map.of("xltx", "039"));
mimeTypesMapping.put("application/vnd.openxmlformats-officedocument.presentationml.template", Map.of("potx", "040"));
mimeTypesMapping.put("application/xml-dtd", Map.of("dtd", "041"));
mimeTypesMapping.put("application/vnd.ms-project", Map.of("mpp", "042"));
mimeTypesMapping.put("application/vnd.oasis.opendocument.text-template", Map.of("ott", "043"));
mimeTypesMapping.put("text/plain", Map.of("txt", "045"));
mimeTypesMapping.put("application/x-pkcs7-certificates", Map.of("p7b", "046"));
mimeTypesMapping.put("application/pkcs7-mime", Map.of("p7c", "047", "p7m", "048"));
mimeTypesMapping.put("application/pkcs7-signature", Map.of("p7s", "049"));
mimeTypesMapping.put("application/vnd.etsi.asic-s+zip", Map.of("asics", "050"));
mimeTypesMapping.put("application/scvp-cv-response", Map.of("scs", "051"));
}
public static String getXdomeaCode(String mimeType, String extension) {
var fileExtensionToCodeMapping = getFileExtensionToCodeMapping(mimeType);
if (hasSingleExtensionMapping(fileExtensionToCodeMapping)) {
return getCodeOrDefault(fileExtensionToCodeMapping);
}
return getCodeForExtensionOrDefault(extension, fileExtensionToCodeMapping);
}
private static Map<String, String> getFileExtensionToCodeMapping(String mimeType) {
return mimeTypesMapping.getOrDefault(Objects.requireNonNullElse(mimeType, StringUtils.EMPTY), Collections.emptyMap());
}
private static boolean hasSingleExtensionMapping(Map<String, String> fileExtensionToCodeMapping) {
return fileExtensionToCodeMapping.entrySet().size() == 1;
}
private static String getCodeOrDefault(Map<String, String> fileExtensionToCodeMapping) {
return fileExtensionToCodeMapping.values().stream().findFirst().orElse(SONSTIGES_CODE);
}
private static String getCodeForExtensionOrDefault(String extension, Map<String, String> fileExtensionToCodeMapping) {
return fileExtensionToCodeMapping.getOrDefault(Objects.requireNonNullElse(extension, StringUtils.EMPTY), SONSTIGES_CODE);
}
}
package de.ozgcloud.alfa.common;
public enum DatentypCode {
STRING("038"), DATE("005");
private String code;
DatentypCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
package de.ozgcloud.alfa.common;
import de.ozgcloud.alfa.common.file.OzgFile;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExportFilenameGenerator {
public static String generateExportFilename(OzgFile ozgFile) {
return String.format("%s_%s", UUIDConverter.fromObjectId(ozgFile.getId().toString()), ozgFile.getName());
}
}
package de.ozgcloud.alfa.common;
import de.xoev.xdomea.IdentifikationObjektType;
public class IdentifikationObjektTypeBuilder {
private String objectID;
private Long ordinalNumber;
public static IdentifikationObjektTypeBuilder builder() {
return new IdentifikationObjektTypeBuilder();
}
public IdentifikationObjektTypeBuilder withObjectID(String objectID) {
this.objectID = objectID;
return this;
}
public IdentifikationObjektTypeBuilder withOrdinalNumber(Long ordinalNumber) {
this.ordinalNumber = ordinalNumber;
return this;
}
public IdentifikationObjektType build() {
var identifikation = new IdentifikationObjektType();
identifikation.setID(UUIDConverter.fromObjectId(objectID));
identifikation.setNummerImUebergeordnetenContainer(ordinalNumber);
return identifikation;
}
}
package de.ozgcloud.alfa.common;
import java.time.ZonedDateTime;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.xoev.xdomea.PrimaerdokumentType;
public class PrimaerdokumentTypeBuilder {
private OzgFile ozgFile;
private String ersteller;
private ZonedDateTime createdAt;
public static PrimaerdokumentTypeBuilder builder() {
return new PrimaerdokumentTypeBuilder();
}
public PrimaerdokumentTypeBuilder withOzgFile(OzgFile ozgFile) {
this.ozgFile = ozgFile;
return this;
}
public PrimaerdokumentTypeBuilder withErsteller(String ersteller) {
this.ersteller = ersteller;
return this;
}
public PrimaerdokumentTypeBuilder withCreatedAt(ZonedDateTime createdAt) {
this.createdAt = createdAt;
return this;
}
public PrimaerdokumentType build() {
if (ozgFile == null) {
throw new IllegalStateException("Can not build Primaerdokument when ozg file is null");
}
var primaerdokument = new PrimaerdokumentType();
primaerdokument.setDateiname(ExportFilenameGenerator.generateExportFilename(ozgFile));
primaerdokument.setDateinameOriginal(ozgFile.getName());
primaerdokument.setErsteller(ersteller);
primaerdokument.setDatumUhrzeit(DateConverter.toXmlGregorianCalendar(createdAt));
return primaerdokument;
}
}
package de.ozgcloud.alfa.common;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
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]+)$");
public static String fromObjectId(String objectId) {
var matcher = UUID_SPLIT_PATTERN.matcher(objectId);
if (matcher.find()) {
var lastGroup = StringUtils.leftPad(matcher.group(5), 12, "0");
return String.format("%s-%s-%s-%s-%s", matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), lastGroup);
}
throw new IllegalArgumentException(String.format("Invalid object id %s", objectId));
}
}
package de.ozgcloud.alfa.common;
import java.time.ZonedDateTime;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.xoev.xdomea.DateiformatCodeType;
import de.xoev.xdomea.FormatType;
import de.xoev.xdomea.VersionType;
public class VersionTypeBuilder {
public static final String VERSION_NUMMER = "1";
public static final String DATEI_FORMAT_LIST_URI = "urn:xoev-de:xdomea:codeliste:dateiformat";
public static final String LIST_VERSION_ID = "2.0";
private OzgFile ozgFile;
private ZonedDateTime createdAt;
private String ersteller;
private String sonstigerName;
public static VersionTypeBuilder builder() {
return new VersionTypeBuilder();
}
public VersionTypeBuilder withOzgFile(OzgFile ozgFile) {
this.ozgFile = ozgFile;
return this;
}
public VersionTypeBuilder withCreatedAt(ZonedDateTime createdAt) {
this.createdAt = createdAt;
return this;
}
public VersionTypeBuilder withErsteller(String ersteller) {
this.ersteller = ersteller;
return this;
}
public VersionTypeBuilder withSonstigerName(String sonstigerName) {
this.sonstigerName = sonstigerName;
return this;
}
public VersionType build() {
var versionType = new VersionType();
versionType.setNummer(VERSION_NUMMER);
versionType.getFormat().add(createFormatType());
return versionType;
}
FormatType createFormatType() {
var formatType = new FormatType();
formatType.setName(createDateiformatCodeType());
formatType.setVersion(StringUtils.EMPTY);
formatType.setSonstigerName(sonstigerName);
formatType.setPrimaerdokument(PrimaerdokumentTypeBuilder.builder()
.withCreatedAt(createdAt)
.withErsteller(ersteller)
.withOzgFile(ozgFile)
.build());
return formatType;
}
DateiformatCodeType createDateiformatCodeType() {
var dateiformatCode = new DateiformatCodeType();
dateiformatCode.setCode(DateiformatCode.getXdomeaCode(ozgFile.getContentType(), FilenameUtils.getExtension(ozgFile.getName()).toLowerCase()));
dateiformatCode.setListURI(DATEI_FORMAT_LIST_URI);
dateiformatCode.setListVersionID(LIST_VERSION_ID);
return dateiformatCode;
}
}
package de.ozgcloud.alfa.export;
import java.util.HashMap;
import java.util.Map;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.validation.Validator;
import jakarta.xml.bind.Marshaller;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Configuration
class ExportConfiguration {
static final boolean JAXB_FORMATTED_OUTPUT = true;
static final String PROPERTY_NAMESPACE_PREFIX_MAPPER = "org.glassfish.jaxb.namespacePrefixMapper";
static final String CONTEXT_PATH = "de.xoev.xdomea";
private final XdomeaNamespacePrefixMapper prefixMapper;
@Bean
static Validator configurationPropertiesValidator() {
return new XdomeaPropertiesValidator();
}
@Bean
Jaxb2Marshaller marshaller() {
var marshaller = new Jaxb2Marshaller();
marshaller.setContextPaths(CONTEXT_PATH);
marshaller.setMarshallerProperties(createMarshallerProperties());
return marshaller;
}
Map<String, Object> createMarshallerProperties() {
var props = new HashMap<String, Object>();
props.put(Marshaller.JAXB_FORMATTED_OUTPUT, JAXB_FORMATTED_OUTPUT);
props.put(PROPERTY_NAMESPACE_PREFIX_MAPPER, prefixMapper);
return props;
}
}
package de.ozgcloud.alfa.export;
import java.util.Set;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.xoev.xdomea.AbgabeAbgabe0401;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
class ExportData {
private String exportFilename;
private AbgabeAbgabe0401 abgabe;
private Set<OzgFile> exportFiles;
}
package de.ozgcloud.alfa.export;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import de.ozgcloud.alfa.bescheid.ExportBescheidService;
import de.ozgcloud.alfa.common.ExportFilenameGenerator;
import de.ozgcloud.alfa.common.file.OzgFile;
import de.ozgcloud.alfa.file.ExportFileService;
import de.ozgcloud.alfa.historie.ExportHistorieService;
import de.ozgcloud.alfa.kommentar.ExportKommentarService;
import de.ozgcloud.alfa.postfach.ExportNachrichtService;
import de.ozgcloud.alfa.vorgang.Eingang;
import de.ozgcloud.alfa.vorgang.EingangHeader;
import de.ozgcloud.alfa.vorgang.ExportVorgangService;
import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
import de.ozgcloud.common.binaryfile.TempFileUtils;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.xoev.xdomea.AbgabeAbgabe0401;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
class ExportService {
static final String EXPORT_FILENAME_SUFFIX = "_Abgabe.Abgabe.0401.xml";
private static final String EXPORT_FILENAME_TEMPLATE = "%s" + EXPORT_FILENAME_SUFFIX;
private final XdomeaXmlMarshaller xDomeaXmlMarshaller;
private final ExportFileService exportFileService;
private final ExportVorgangService exportVorgangService;
private final ExportHistorieService exportHistorieService;
private final ExportKommentarService exportKommentarService;
private final ExportNachrichtService exportNachrichtService;
private final ExportBescheidService exportBescheidService;
public void writeExport(String vorgangId, String filenameId, OutputStream out) {
var exportData = collectExportData(vorgangId, filenameId);
var zipFile = createZipFile(exportData);
writeZipFileContent(zipFile, out);
}
ExportData collectExportData(String vorgangId, String filenameId) {
var vorgang = exportVorgangService.getVorgang(vorgangId);
var kommentarsData = exportKommentarService.createExportData(vorgang);
var postfachMailData = exportNachrichtService.createExportData(vorgang);
var bescheidData = exportBescheidService.createExportData(vorgang);
var representations = exportFileService.getRepresentations(vorgang).toList();
var attachments = exportFileService.getAttachments(vorgang).toList();
var formEngineName = getFormEngineName(vorgang);
var abgabe = XdomeaNachrichtBuilder.builder()
.withKopf(exportVorgangService.createKopf(vorgang))
.withVorgang(exportVorgangService.createVorgangType(vorgang))
.withAktenzeichen(exportVorgangService.createAkteType(vorgang))
.withRepresentations(exportFileService.createDokumentTypes(representations, formEngineName).toList())
.withAttachments(exportFileService.createDokumentTypes(attachments, formEngineName).toList())
.withHistorie(exportHistorieService.createHistorienProtokollInformationTypes(vorgang).toList())
.withKommentare(kommentarsData.getDokumentTypes())
.withPostfachMails(postfachMailData.getDokumentTypes())
.withBescheids(bescheidData.getDokumentTypes())
.build();
var exportFiles = Stream
.of(representations.stream(), attachments.stream(),
kommentarsData.getAttachments().stream(),
postfachMailData.getAttachments().stream(),
bescheidData.getFiles().stream())
.flatMap(s -> s)
.collect(Collectors.toSet());
return ExportData.builder().abgabe(abgabe).exportFilename(buildXmlFilename(filenameId)).exportFiles(exportFiles).build();
}
String getFormEngineName(VorgangWithEingang vorgang) {
return Optional.ofNullable(vorgang.getEingang())
.map(Eingang::getHeader)
.map(EingangHeader::getFormEngineName).orElse(StringUtils.EMPTY);
}
String buildXmlFilename(String filenameId) {
return String.format(EXPORT_FILENAME_TEMPLATE, filenameId);
}
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(), createXmlContent(exportData.getAbgabe()), zipOutputStream);
putFilesIntoZip(exportData.getExportFiles(), zipOutputStream);
return file;
} catch (Exception e) {
throw new TechnicalException("Error creating xdomea zip file", e);
}
}
void putZipEntry(String fileName, String fileData, ZipOutputStream zipOutputStream) throws IOException {
var entry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(entry);
zipOutputStream.write(fileData.getBytes(StandardCharsets.UTF_8));
zipOutputStream.closeEntry();
}
private void putFilesIntoZip(Set<OzgFile> ozgFiles, ZipOutputStream zipOutputStream) {
ozgFiles.forEach(ozgFile -> putOzgFileIntoZip(ozgFile, zipOutputStream));
}
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 TechnicalException("Cannot add file to ZIP.", e);
}
}
void writeZipFileContent(File file, OutputStream outputStream) {
try (var fileInputStream = new FileInputStream(file)) {
fileInputStream.transferTo(outputStream);
} catch (Exception e) {
throw new TechnicalException("Error writing xdomea zip file to output stream", e);
}
}
}
package de.ozgcloud.alfa.export;
enum XdomeaMedienart {
ELEKTRONISCHES_DOKUMENT("001");
private String code;
XdomeaMedienart(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
package de.ozgcloud.alfa.export;
import java.util.Collections;
import java.util.List;
import de.xoev.xdomea.AbgabeAbgabe0401;
import de.xoev.xdomea.AbgabeAbgabe0401.Schriftgutobjekt;
import de.xoev.xdomea.AkteType;
import de.xoev.xdomea.DokumentType;
import de.xoev.xdomea.HistorienProtokollInformationType;
import de.xoev.xdomea.NkAbgabeType;
import de.xoev.xdomea.VorgangType;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
class XdomeaNachrichtBuilder {
private VorgangType vorgang;
private NkAbgabeType kopf;
private AkteType aktenzeichen;
private List<DokumentType> representations = Collections.emptyList();
private List<DokumentType> attachments = Collections.emptyList();
private List<DokumentType> kommentare = Collections.emptyList();
private List<DokumentType> postfachMails = Collections.emptyList();
private List<DokumentType> bescheids = Collections.emptyList();
private List<HistorienProtokollInformationType> historie = Collections.emptyList();
public static XdomeaNachrichtBuilder builder() {
return new XdomeaNachrichtBuilder();
}
public XdomeaNachrichtBuilder withKopf(NkAbgabeType kopf) {
this.kopf = kopf;
return this;
}
public XdomeaNachrichtBuilder withVorgang(VorgangType vorgangType) {
this.vorgang = vorgangType;
return this;
}
public XdomeaNachrichtBuilder withAktenzeichen(AkteType akteType) {
this.aktenzeichen = akteType;
return this;
}
public XdomeaNachrichtBuilder withRepresentations(List<DokumentType> representations) {
this.representations = representations;
return this;
}
public XdomeaNachrichtBuilder withAttachments(List<DokumentType> attachments) {
this.attachments = attachments;
return this;
}
public XdomeaNachrichtBuilder withHistorie(List<HistorienProtokollInformationType> historie) {
this.historie = historie;
return this;
}
public XdomeaNachrichtBuilder withKommentare(List<DokumentType> kommentare) {
this.kommentare = kommentare;
return this;
}
public XdomeaNachrichtBuilder withPostfachMails(List<DokumentType> postfachMails) {
this.postfachMails = postfachMails;
return this;
}
public XdomeaNachrichtBuilder withBescheids(List<DokumentType> bescheids) {
this.bescheids = bescheids;
return this;
}
public AbgabeAbgabe0401 build() {
addVorgangDokumente();
addVorgangChangeHistory();
return createAbgabeType();
}
void addVorgangDokumente() {
representations.forEach(vorgang.getDokument()::add);
attachments.forEach(vorgang.getDokument()::add);
kommentare.forEach(vorgang.getDokument()::add);
postfachMails.forEach(vorgang.getDokument()::add);
bescheids.forEach(vorgang.getDokument()::add);
}
void addVorgangChangeHistory() {
historie.forEach(vorgang.getHistorienProtokollInformation()::add);
}
AbgabeAbgabe0401 createAbgabeType() {
var abgabeType = new AbgabeAbgabe0401();
abgabeType.setKopf(kopf);
abgabeType.getSchriftgutobjekt().add(createSchriftgutobjektVorgang());
abgabeType.getSchriftgutobjekt().add(createSchriftgutobjektAkte());
return abgabeType;
}
private Schriftgutobjekt createSchriftgutobjektVorgang() {
var schriftgutobjekt = new Schriftgutobjekt();
schriftgutobjekt.setVorgang(vorgang);
return schriftgutobjekt;
}
private Schriftgutobjekt createSchriftgutobjektAkte() {
var schriftgutobjekt = new Schriftgutobjekt();
schriftgutobjekt.setAkte(aktenzeichen);
return schriftgutobjekt;
}
}
package de.ozgcloud.alfa.export;
import java.util.Map;
import org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper;
import org.springframework.stereotype.Component;
@Component
class XdomeaNamespacePrefixMapper extends NamespacePrefixMapper {
static final String XDOMEA_NAMESPACE_URI = "urn:xoev-de:xdomea:schema:3.0.0";
static final String XDOMEA_NAMESPACE_PREFIX = "xdomea";
static final String XDOMEA_NAMESPACE_DINSPEC = "dinspec91379";
static final String XDOMEA_NAMESPACE_DINSPEC_URI = "urn:xoev-de:kosit:xoev:datentyp:din-spec-91379_2019-03";
static final String XDOMEA_NAMESPACE_GML = "gml";
static final String XDOMEA_NAMESPACE_GML_URI = "http://www.opengis.net/gml/3.2";
static final String XDOMEA_NAMESPACE_XOEV_CODE = "xoev-code";
static final String XDOMEA_NAMESPACE_XOEV_CODE_URI = "http://xoev.de/schemata/code/1_0";
static final String XDOMEA_NAMESPACE_XOEV_LC = "xoev-lc";
static final String XDOMEA_NAMESPACE_XOEV_LC_URI = "http://xoev.de/latinchars/1_1/datatypes";
private static final Map<String, String> NAMESPACE_MAP = Map.of(
XDOMEA_NAMESPACE_URI, XDOMEA_NAMESPACE_PREFIX,
XDOMEA_NAMESPACE_DINSPEC_URI, XDOMEA_NAMESPACE_DINSPEC,
XDOMEA_NAMESPACE_GML_URI, XDOMEA_NAMESPACE_GML,
XDOMEA_NAMESPACE_XOEV_CODE_URI, XDOMEA_NAMESPACE_XOEV_CODE,
XDOMEA_NAMESPACE_XOEV_LC_URI, XDOMEA_NAMESPACE_XOEV_LC);
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
return NAMESPACE_MAP.getOrDefault(namespaceUri, suggestion);
}
@Override
public String[] getPreDeclaredNamespaceUris() {
return new String[] {
XDOMEA_NAMESPACE_DINSPEC_URI,
XDOMEA_NAMESPACE_GML_URI,
XDOMEA_NAMESPACE_XOEV_CODE_URI,
XDOMEA_NAMESPACE_XOEV_LC_URI
};
}
}
package de.ozgcloud.alfa.export;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Configuration
@ConfigurationProperties("ozgcloud.xdomea")
@Validated
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class XdomeaProperties {
private String behoerdenschluessel;
private String behoerdenschluesselUri;
private String behoerdenschluesselVersion;
}
package de.ozgcloud.alfa.export;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import de.ozgcloud.common.errorhandling.TechnicalException;
public class XdomeaPropertiesValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return XdomeaProperties.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
var properties = (XdomeaProperties) target;
validateBehoerdenschluesselProperties(errors, properties);
}
private void validateBehoerdenschluesselProperties(Errors errors, XdomeaProperties properties) {
if (StringUtils.isNotBlank(properties.getBehoerdenschluessel())) {
validateNotBlank("behoerdenschluesselUri", properties, errors);
validateNotBlank("behoerdenschluesselVersion", properties, errors);
}
}
private void validateNotBlank(String propertyName, XdomeaProperties properties, Errors errors) {
getPropertyValue(propertyName, properties);
if (StringUtils.isBlank(getPropertyValue(propertyName, properties))) {
errors.rejectValue(propertyName, String.format("ozgcloud.xdomea.%s.empty", propertyName), String.format("%s must be set", propertyName));
}
}
private static String getPropertyValue(String fieldName, XdomeaProperties properties) {
try {
return BeanUtils.getSimpleProperty(properties, fieldName);
} catch (Exception e) {
throw new TechnicalException("Property does not exist", e);
}
}
}
package de.ozgcloud.alfa.export;
import java.io.StringWriter;
import javax.xml.transform.stream.StreamResult;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Component;
import de.xoev.xdomea.AbgabeAbgabe0401;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Component
public class XdomeaXmlMarshaller {
private final Jaxb2Marshaller marshaller;
public String marshal(AbgabeAbgabe0401 abgabe) {
var stringWriter = new StringWriter();
marshaller.marshal(abgabe, new StreamResult(stringWriter));
return stringWriter.toString();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment