From 671c277b85d32bf040be34048e6167d6675d747e Mon Sep 17 00:00:00 2001
From: Riegel <alexander.riegel@hft-stuttgart.de>
Date: Thu, 12 Dec 2024 12:45:29 +0100
Subject: [PATCH] Style: Reformat code

---
 .../citydoctor2/parser/CityGmlParser.java     | 1310 +++++++-------
 .../citydoctor2/zip/CityGmlZipArchive.java    |   25 +-
 .../citydoctor2/zip/CityGmlZipEntry.java      |   37 +-
 .../stuttgart/citydoctor2/zip/ZipTest.java    |   17 +-
 .../stuttgart/citydoctor2/check/Checker.java  | 1559 ++++++++---------
 .../citydoctor2/check/CheckerTest.java        |  177 +-
 6 files changed, 1564 insertions(+), 1561 deletions(-)

diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java
index 73501da..765bb50 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java
@@ -1,6 +1,6 @@
 /*-
  *  Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
- * 
+ *
  *  This file is part of CityDoctor2.
  *
  *  CityDoctor2 is free software: you can redistribute it and/or modify
@@ -18,28 +18,16 @@
  */
 package de.hft.stuttgart.citydoctor2.parser;
 
-import java.io.*;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.XMLConstants;
-import javax.xml.namespace.QName;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
-
+import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
+import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
+import de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper;
+import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler;
+import de.hft.stuttgart.citydoctor2.math.Vector3d;
+import de.hft.stuttgart.citydoctor2.utils.Localization;
 import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
 import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile;
+import de.hft.stuttgart.quality.QualityADEContext;
+import de.hft.stuttgart.quality.QualityADEModule;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -69,605 +57,623 @@ import org.locationtech.proj4j.CoordinateReferenceSystem;
 import org.locationtech.proj4j.ProjCoordinate;
 import org.locationtech.proj4j.proj.Projection;
 import org.locationtech.proj4j.units.Units;
-import org.xml.sax.*;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
 import org.xmlobjects.schema.SchemaHandler;
 import org.xmlobjects.schema.SchemaHandlerException;
 import org.xmlobjects.stream.XMLReader;
 import org.xmlobjects.stream.XMLReaderFactory;
 
-import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
-import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
-import de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper;
-import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler;
-import de.hft.stuttgart.citydoctor2.math.Vector3d;
-import de.hft.stuttgart.citydoctor2.utils.Localization;
-import de.hft.stuttgart.quality.QualityADEContext;
-import de.hft.stuttgart.quality.QualityADEModule;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Utility class to parse CityGML files.
- * 
- * @author Matthias Betz
  *
+ * @author Matthias Betz
  */
 public class CityGmlParser {
 
-	private static final String CITY_OBJECT_MEMBER = "cityObjectMember";
-
-	private static final String WGS_84 = "EPSG:4326";
-
-	private static final Logger logger = LogManager.getLogger(CityGmlParser.class);
-
-	private static final CRSFactory CRS_FACTORY = new CRSFactory();
-	// EPSG:31467
-	private static final Pattern P_EPSG = Pattern.compile("^(EPSG:\\d+)$");
-	// urn:ogc:def:crs,crs:EPSG:6.12:31467,crs:EPSG:6.12:5783
-	// or
-	// urn:ogc:def:crs,crs:EPSG::28992
-	private static final Pattern P_OGC = Pattern.compile("urn:ogc:def:crs,crs:EPSG:[\\d\\.]*:([\\d]+)\\D*");
-
-	private static final Pattern P_OGC2 = Pattern.compile("urn:ogc:def:crs:EPSG:[\\d\\.]*:([\\d]+)\\D*");
-
-	// urn:adv:crs:DE_DHDN_3GK3*DE_DHHN92_NH
-	// urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH
-	private static final Pattern P_URN = Pattern.compile("urn:adv:crs:([^\\*]+)");
-
-	private static final SAXParserFactory FACTORY;
-
-	private static CityGMLContext context;
-	private static List<QName> chunkProperties = new ArrayList<>();
-
-
-	static {
-		System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
-		FACTORY = SAXParserFactory.newInstance();
-		try {
-			FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
-		} catch (SAXNotRecognizedException | SAXNotSupportedException | ParserConfigurationException e) {
-			logger.catching(e);
-		}
-
-		chunkProperties.add(new QName(CityGMLConstants.CITYGML_1_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
-		chunkProperties.add(new QName(CityGMLConstants.CITYGML_2_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
-		chunkProperties.add(new QName(CityGMLConstants.CITYGML_3_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
-	}
-
-	private CityGmlParser() {
-	}
-
-	public static synchronized CityGMLContext getContext() {
-		if (context == null) {
-			try {
-				context = CityGMLContext.newInstance(CityGmlParser.class.getClassLoader());
-				// also setup ades
-				ADERegistry adeRegistry = ADERegistry.getInstance();
-				adeRegistry.loadADE(new QualityADEContext());
-			} catch (CityGMLContextException e) {
-				logger.fatal("Unable to create citygml4j context", e);
-				throw new IllegalStateException("Unable to create citygml4j context");
-			} catch (ADEException e) {
-				logger.fatal("Unable to add ADE plugins to citygml4j", e);
-				throw new IllegalStateException("Unable to add ADE plugins to citygml4j");
-			}
-		}
-		return context;
-	}
-
-	public static CityDoctorModel parseCityGmlFileSilently(String file, ParserConfiguration config)
-			throws CityGmlParseException, InvalidGmlFileException {
-		return parseCityGmlFile(file, config, null, null, false);
-	}
-
-	public static CityDoctorModel parseCityGmlFile(String file, ParserConfiguration config)
-			throws CityGmlParseException, InvalidGmlFileException {
-		return parseCityGmlFile(file, config, null, null, true);
-	}
-
-	public static CityDoctorModel parseCityGmlFile(String file, ParserConfiguration config, ProgressListener l)
-			throws CityGmlParseException, InvalidGmlFileException {
-		return parseCityGmlFile(file, config, l, null, true);
-	}
-
-	public static CityDoctorModel parseCityGmlFile(String filePath, ParserConfiguration config, ProgressListener l,
-			GMLValidationHandler handler, boolean verbose) throws CityGmlParseException, InvalidGmlFileException {
-		CityGMLContext context = getContext();
-		Path file = Paths.get(filePath);
-		if (config.getValidate()) {
-			List<String> messages = validateFile(context, handler, file);
-			if (!messages.isEmpty()) {
-				throw new InvalidGmlFileException("Invalid GML File. First error: \n" + messages.get(0));
-			}
-		}
-
-		try {
-			parseEpsgCodeFromFile(file, config);
-			CityGMLInputFactory in = context.createCityGMLInputFactory()
-					.withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
-			try (ObservedInputStream ois = new ObservedInputStream(file.toFile())) {
-				if (l != null) {
-					ois.addListener(l::updateProgress);
-				}
-				return readAndKeepFeatures(config, file, in, ois, verbose);
-			}
-		} catch (CityGMLReadException | IOException e) {
-			throw new CityGmlParseException("Failed to read CityGML file", e);
-		}
-	}
-
-	public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config)
+    private static final String CITY_OBJECT_MEMBER = "cityObjectMember";
+
+    private static final String WGS_84 = "EPSG:4326";
+
+    private static final Logger logger = LogManager.getLogger(CityGmlParser.class);
+
+    private static final CRSFactory CRS_FACTORY = new CRSFactory();
+    // EPSG:31467
+    private static final Pattern P_EPSG = Pattern.compile("^(EPSG:\\d+)$");
+    // urn:ogc:def:crs,crs:EPSG:6.12:31467,crs:EPSG:6.12:5783
+    // or
+    // urn:ogc:def:crs,crs:EPSG::28992
+    private static final Pattern P_OGC = Pattern.compile("urn:ogc:def:crs,crs:EPSG:[\\d\\.]*:([\\d]+)\\D*");
+
+    private static final Pattern P_OGC2 = Pattern.compile("urn:ogc:def:crs:EPSG:[\\d\\.]*:([\\d]+)\\D*");
+
+    // urn:adv:crs:DE_DHDN_3GK3*DE_DHHN92_NH
+    // urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH
+    private static final Pattern P_URN = Pattern.compile("urn:adv:crs:([^\\*]+)");
+
+    private static final SAXParserFactory FACTORY;
+
+    private static CityGMLContext context;
+    private static List<QName> chunkProperties = new ArrayList<>();
+
+
+    static {
+        System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
+        FACTORY = SAXParserFactory.newInstance();
+        try {
+            FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
+        } catch (SAXNotRecognizedException | SAXNotSupportedException | ParserConfigurationException e) {
+            logger.catching(e);
+        }
+
+        chunkProperties.add(new QName(CityGMLConstants.CITYGML_1_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
+        chunkProperties.add(new QName(CityGMLConstants.CITYGML_2_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
+        chunkProperties.add(new QName(CityGMLConstants.CITYGML_3_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
+    }
+
+    private CityGmlParser() {
+    }
+
+    public static synchronized CityGMLContext getContext() {
+        if (context == null) {
+            try {
+                context = CityGMLContext.newInstance(CityGmlParser.class.getClassLoader());
+                // also setup ades
+                ADERegistry adeRegistry = ADERegistry.getInstance();
+                adeRegistry.loadADE(new QualityADEContext());
+            } catch (CityGMLContextException e) {
+                logger.fatal("Unable to create citygml4j context", e);
+                throw new IllegalStateException("Unable to create citygml4j context");
+            } catch (ADEException e) {
+                logger.fatal("Unable to add ADE plugins to citygml4j", e);
+                throw new IllegalStateException("Unable to add ADE plugins to citygml4j");
+            }
+        }
+        return context;
+    }
+
+    public static CityDoctorModel parseCityGmlFileSilently(String file, ParserConfiguration config)
+            throws CityGmlParseException, InvalidGmlFileException {
+        return parseCityGmlFile(file, config, null, null, false);
+    }
+
+    public static CityDoctorModel parseCityGmlFile(String file, ParserConfiguration config)
+            throws CityGmlParseException, InvalidGmlFileException {
+        return parseCityGmlFile(file, config, null, null, true);
+    }
+
+    public static CityDoctorModel parseCityGmlFile(String file, ParserConfiguration config, ProgressListener l)
+            throws CityGmlParseException, InvalidGmlFileException {
+        return parseCityGmlFile(file, config, l, null, true);
+    }
+
+    public static CityDoctorModel parseCityGmlFile(String filePath, ParserConfiguration config, ProgressListener l,
+                                                   GMLValidationHandler handler, boolean verbose) throws CityGmlParseException, InvalidGmlFileException {
+        CityGMLContext context = getContext();
+        Path file = Paths.get(filePath);
+        if (config.getValidate()) {
+            List<String> messages = validateFile(context, handler, file);
+            if (!messages.isEmpty()) {
+                throw new InvalidGmlFileException("Invalid GML File. First error: \n" + messages.get(0));
+            }
+        }
+
+        try {
+            parseEpsgCodeFromFile(file, config);
+            CityGMLInputFactory in = context.createCityGMLInputFactory()
+                    .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
+            try (ObservedInputStream ois = new ObservedInputStream(file.toFile())) {
+                if (l != null) {
+                    ois.addListener(l::updateProgress);
+                }
+                return readAndKeepFeatures(config, file, in, ois, verbose);
+            }
+        } catch (CityGMLReadException | IOException e) {
+            throw new CityGmlParseException("Failed to read CityGML file", e);
+        }
+    }
+
+    public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config)
             throws CityGmlParseException, InvalidGmlFileException, IOException {
-		CityGMLContext context = getContext();
-
-		if (config.getValidate()) {
-			try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)){
-				List<String> messages = validateStream(entryFile.getInputStream(),context);
-				if (!messages.isEmpty()) {
-					throw new InvalidGmlFileException("Invalid GML File. First error: \n" + messages.get(0));
-				}
-			} catch (Exception e) {
+        CityGMLContext context = getContext();
+
+        if (config.getValidate()) {
+            try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
+                List<String> messages = validateStream(entryFile.getInputStream(), context);
+                if (!messages.isEmpty()) {
+                    throw new InvalidGmlFileException("Invalid GML File. First error: \n" + messages.get(0));
+                }
+            } catch (Exception e) {
                 throw new CityGmlParseException(e);
             }
 
         }
-		return decompressAndParseCityGmlEntry(entry, config, context);
-	}
-
-	public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config, CityGMLContext context)
-			throws CityGmlParseException {
-		return decompressAndParseCityGmlEntry(entry, config, null, context);
-	}
-
-	public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l, CityGMLContext context)
-			throws CityGmlParseException {
-
-		try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)){
-			BufferedInputStream bis = new BufferedInputStream(entryFile.getInputStream());
-			readEpsgCodeFromInputStream(bis,config);
-			CityGMLInputFactory in = context.createCityGMLInputFactory()
-					.withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
-			try(ObservedInputStream ois = new ObservedInputStream(bis, bis.available())){
-				if (l != null){
-					ois.addListener(l::updateProgress);
-				}
-				return readAndKeepFeatures(config, entry, in, ois, false);
-			}
-		} catch (CityGMLReadException | IOException e) {
-			throw new CityGmlParseException("Failed to read CityGML file", e);
-		} catch (Exception e) {
+        return decompressAndParseCityGmlEntry(entry, config, context);
+    }
+
+    public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config, CityGMLContext context)
+            throws CityGmlParseException {
+        return decompressAndParseCityGmlEntry(entry, config, null, context);
+    }
+
+    public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l, CityGMLContext context)
+            throws CityGmlParseException {
+
+        try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
+            BufferedInputStream bis = new BufferedInputStream(entryFile.getInputStream());
+            readEpsgCodeFromInputStream(bis, config);
+            CityGMLInputFactory in = context.createCityGMLInputFactory()
+                    .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
+            try (ObservedInputStream ois = new ObservedInputStream(bis, bis.available())) {
+                if (l != null) {
+                    ois.addListener(l::updateProgress);
+                }
+                return readAndKeepFeatures(config, entry, in, ois, false);
+            }
+        } catch (CityGMLReadException | IOException e) {
+            throw new CityGmlParseException("Failed to read CityGML file", e);
+        } catch (Exception e) {
+            throw new CityGmlParseException(e);
+        }
+    }
+
+    private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, CityGmlZipEntry entry,
+                                                       CityGMLInputFactory inputFactory, ObservedInputStream ois, boolean verbose) throws CityGMLReadException {
+        return readAndKeepModel(new Citygml3FeatureMapper(config, entry), inputFactory, ois, verbose);
+    }
+
+    private static List<String> validateStream(InputStream vis, CityGMLContext context) throws CityGmlParseException {
+        GMLValidationHandler handler = new GMLValidationHandler();
+
+        try {
+            BufferedInputStream bis = new BufferedInputStream(vis);
+            SchemaHandler schemaHandler = new ValidationSchemaHandler(context.getDefaultSchemaHandler());
+            readAdditionalSchemaDefinitions(context, bis, schemaHandler);
+            Source[] schemas = schemaHandler.getSchemas();
+            SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+            schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+            Schema schema = schemaFactory.newSchema(schemas);
+            Validator validator = schema.newValidator();
+            validator.setErrorHandler(handler);
+            validator.validate(new StreamSource(bis));
+            return handler.getMessages();
+        } catch (SchemaHandlerException | SAXException | IOException e) {
+            throw new CityGmlParseException("Failed to validate CityGML file", e);
+        }
+    }
+
+    private static void readAdditionalSchemaDefinitions(CityGMLContext context, BufferedInputStream bis, SchemaHandler schemaHandler)
+            throws CityGmlParseException {
+        bis.mark(Integer.MAX_VALUE);
+        try (XMLReader reader = XMLReaderFactory.newInstance(context.getXMLObjects())
+                .withSchemaHandler(schemaHandler)
+                .createReader(bis)) {
+            reader.nextTag();
+            bis.reset();
+        } catch (Exception e) {
+            throw new CityGmlParseException("Failed to read Schema from stream.", e);
+        }
+    }
+
+    private static void readEpsgCodeFromInputStream(BufferedInputStream bis, ParserConfiguration config) throws CityGmlParseException {
+        try {
+            // Mark start position of GML-"file"
+            bis.mark(Integer.MAX_VALUE);
+            // Buffer the first 10000 chars of the Stream, EPSG/envelope info should be found within that range
+            int peekingWidth = Math.min(10000, bis.available());
+            byte[] buf = new byte[peekingWidth];
+            bis.read(buf, 0, peekingWidth);
+            bis.reset();
+            parseEpsgCodeFromBuffer(buf, config);
+        } catch (ParserConfigurationException | SAXException | IOException e) {
+            throw new CityGmlParseException("Failed to read CityGML file", e);
+        }
+
+    }
+
+    public static void streamCityGml(CityGmlZipEntry entry, ParserConfiguration config, CityGmlConsumer cityObjectConsumer,
+                                     String outputFile) throws CityGmlParseException, IOException {
+        try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
+            parseEpsgCodeFromStream(entryFile.getInputStream(), config);
+            startReadingCityGmlZipEntry(entry, config, null, cityObjectConsumer, outputFile);
+        } catch (ParserConfigurationException | SAXException | IOException e) {
+            throw new CityGmlParseException("Failed to read CityGML stream", e);
+        }
+    }
+
+    public static void streamCityGml(String file, ParserConfiguration config, CityGmlConsumer cityObjectConsumer,
+                                     String outputFile) throws CityGmlParseException {
+        Path f = Paths.get(file);
+        streamCityGml(f, config, null, cityObjectConsumer, outputFile);
+    }
+
+    public static void streamCityGml(File file, ParserConfiguration parserConfig, CityGmlConsumer cityObjectConsumer,
+                                     String outputFile) throws CityGmlParseException {
+        streamCityGml(file.toPath(), parserConfig, null, cityObjectConsumer, outputFile);
+    }
+
+    public static void streamCityGml(Path file, ParserConfiguration config, ProgressListener l,
+                                     CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGmlParseException {
+        parseEpsgCodeFromFile(file, config);
+        startReadingCityGmlFile(file, config, l, cityObjectConsumer, outputFile);
+    }
+
+    public static CityModel parseOnlyCityModel(File inputFile) throws CityGmlParseException {
+        try {
+            CityGMLInputFactory inputFactory = context.createCityGMLInputFactory()
+                    .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
+            try (CityGMLReader reader = inputFactory.createCityGMLReader(inputFile)) {
+                while (reader.hasNext()) {
+                    AbstractFeature chunk = reader.next();
+                    if (chunk instanceof CityModel cModel) {
+                        cModel.setCityObjectMembers(null);
+                        return cModel;
+                    }
+                }
+            }
+        } catch (CityGMLReadException e) {
             throw new CityGmlParseException(e);
         }
+        throw new CityGmlParseException("Did not find any CityModel in CityGML file");
     }
 
-	private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, CityGmlZipEntry entry,
-													   CityGMLInputFactory inputFactory, ObservedInputStream ois, boolean verbose) throws CityGMLReadException {
-		return readAndKeepModel(new Citygml3FeatureMapper(config, entry), inputFactory, ois, verbose);
-	}
-
-	private static List<String> validateStream(InputStream vis, CityGMLContext context) throws CityGmlParseException {
-		GMLValidationHandler handler = new GMLValidationHandler();
-
-		try {
-			BufferedInputStream bis = new BufferedInputStream(vis);
-			SchemaHandler schemaHandler = new ValidationSchemaHandler(context.getDefaultSchemaHandler());
-			readAdditionalSchemaDefinitions(context, bis, schemaHandler);
-			Source[] schemas = schemaHandler.getSchemas();
-			SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-			schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-			Schema schema = schemaFactory.newSchema(schemas);
-			Validator validator = schema.newValidator();
-			validator.setErrorHandler(handler);
-			validator.validate(new StreamSource(bis));
-			return handler.getMessages();
-		} catch (SchemaHandlerException | SAXException | IOException e) {
-			throw new CityGmlParseException("Failed to validate CityGML file", e);
-		}
-	}
-
-	private static void readAdditionalSchemaDefinitions(CityGMLContext context, BufferedInputStream bis, SchemaHandler schemaHandler)
-			throws CityGmlParseException {
-		bis.mark(Integer.MAX_VALUE);
-		try (XMLReader reader = XMLReaderFactory.newInstance(context.getXMLObjects())
-				.withSchemaHandler(schemaHandler)
-				.createReader(bis)) {
-			reader.nextTag();
-			bis.reset();
-		} catch (Exception e) {
-			throw new CityGmlParseException("Failed to read Schema from stream.", e);
-		}
-	}
-
-	private static void readEpsgCodeFromInputStream(BufferedInputStream bis, ParserConfiguration config) throws CityGmlParseException {
-		try{
-			// Mark start position of GML-"file"
-			bis.mark(Integer.MAX_VALUE);
-			// Buffer the first 10000 chars of the Stream, EPSG/envelope info should be found within that range
-			int peekingWidth = Math.min(10000, bis.available());
-			byte[] buf = new byte[peekingWidth];
-			bis.read(buf, 0, peekingWidth);
-			bis.reset();
-			parseEpsgCodeFromBuffer(buf, config);
-		} catch (ParserConfigurationException | SAXException | IOException e) {
-			throw new CityGmlParseException("Failed to read CityGML file", e);
-		}
-
-    }
-
-	public static void streamCityGml(CityGmlZipEntry entry, ParserConfiguration config, CityGmlConsumer cityObjectConsumer,
-									 String outputFile) throws CityGmlParseException, IOException {
-		try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
-			parseEpsgCodeFromStream(entryFile.getInputStream(), config);
-			startReadingCityGmlZipEntry(entry, config, null,cityObjectConsumer, outputFile);
-		} catch (ParserConfigurationException | SAXException | IOException e) {
-			throw new CityGmlParseException("Failed to read CityGML stream", e);
-		}
-    }
-
-	public static void streamCityGml(String file, ParserConfiguration config, CityGmlConsumer cityObjectConsumer,
-			String outputFile) throws CityGmlParseException {
-		Path f = Paths.get(file);
-		streamCityGml(f, config, null, cityObjectConsumer, outputFile);
-	}
-
-	public static void streamCityGml(File file, ParserConfiguration parserConfig, CityGmlConsumer cityObjectConsumer,
-			String outputFile) throws CityGmlParseException {
-		streamCityGml(file.toPath(), parserConfig, null, cityObjectConsumer, outputFile);
-	}
-
-	public static void streamCityGml(Path file, ParserConfiguration config, ProgressListener l,
-			CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGmlParseException {
-		parseEpsgCodeFromFile(file, config);
-		startReadingCityGmlFile(file, config, l, cityObjectConsumer, outputFile);
-	}
-
-	public static CityModel parseOnlyCityModel(File inputFile) throws CityGmlParseException {
-		try {
-			CityGMLInputFactory inputFactory = context.createCityGMLInputFactory()
-					.withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
-			try (CityGMLReader reader = inputFactory.createCityGMLReader(inputFile)) {
-				while (reader.hasNext()) {
-					AbstractFeature chunk = reader.next();
-					if (chunk instanceof CityModel cModel) {
-						cModel.setCityObjectMembers(null);
-						return cModel;
-					}
-				}
-			}
-		} catch (CityGMLReadException e) {
-			throw new CityGmlParseException(e);
-		}
-		throw new CityGmlParseException("Did not find any CityModel in CityGML file");
-	}
-
-	private static void startReadingCityGmlFile(Path file, ParserConfiguration config, ProgressListener l,
-												CityGmlConsumer cityObjectConsumer, String outputFile) {
-		try (ObservedInputStream ois = new ObservedInputStream(file.toFile())) {
-			if (l != null) {
-				ois.addListener(l::updateProgress);
-			}
-			readAndDiscardFeatures(file, config, ois, cityObjectConsumer, outputFile);
-		} catch (IOException | CityGMLReadException e) {
-			logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage());
-			logger.catching(Level.ERROR, e);
-		}
-	}
-
-	private static void readAndDiscardFeatures(Path file, ParserConfiguration config, ObservedInputStream ois,
-											   CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
-		Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, file);
-		readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile);
-
-	}
-
-	private static void startReadingCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l,
-													CityGmlConsumer cityObjectConsumer, String outputFile) {
-		try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry);
-			 ObservedInputStream ois = new ObservedInputStream(entryFile.getInputStream(), entry.getFileSize())){
-			if (l != null) {
-				ois.addListener(l::updateProgress);
-			}
-			streamAndDiscardFeatures(entry, config, ois, cityObjectConsumer, outputFile);
-		} catch (IOException | CityGMLReadException e) {
-			logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage());
-			logger.catching(Level.ERROR, e);
-		}
-	}
-
-	private static void streamAndDiscardFeatures(CityGmlZipEntry entry, ParserConfiguration config, ObservedInputStream ois,
-							 CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
-		Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, entry);
-		readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile);
-	}
-
-	private static void readAndDiscardModel(Citygml3FeatureMapper mapper, ObservedInputStream ois,
-			CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
-		getContext();
-		CityGMLInputFactory inputFactory = context.createCityGMLInputFactory()
-				.withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
-		CityGMLChunkWriter writer = null;
-		try (CityGMLReader reader = inputFactory.createCityGMLReader(ois)) {
-
-			CityDoctorModel model = mapper.getModel();
-			boolean isInitialized = false;
-			while (reader.hasNext()) {
-				AbstractFeature chunk = reader.next();
-				if (writer == null) {
-					writer = createCityModelWriter(outputFile, reader);
-				}
-				if (!isInitialized && writer != null && reader.getParentInfo() != null
-						&& reader.getParentInfo().getTypeName().getLocalPart().equals("CityModel")) {
-					FeatureInfo parentInfo = reader.getParentInfo();
-					writer.withCityModelInfo(parentInfo);
-					isInitialized = true;
-				}
-				if (chunk instanceof AbstractCityObject ag) {
-					ag.accept(mapper);
-					drainCityModel(model, cityObjectConsumer);
-					writeAbstractCityObject(writer, ag);
-				} else if (chunk instanceof CityModel cModel) {
-					cModel.setCityObjectMembers(null);
-					mapper.setCityModel(cModel);
-					cityObjectConsumer.accept(cModel);
-					writeCityModel(writer, cModel);
-				} else if (writer != null) {
-					writer.writeMember(chunk);
-				}
-			}
-			// end of stream
-			logger.debug("End of gml file stream");
-		} catch (CityGMLReadException e) {
-			logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage(), e);
-		} catch (CityGMLWriteException e) {
-			logger.error(Localization.getText("CityGmlParser.errorWritingGmlFile"), e.getMessage(), e);
-		} finally {
-			if (writer != null) {
-				try {
-					writer.close();
-				} catch (CityGMLWriteException e) {
-					// ignore
-				}
-			}
-		}
-	}
-
-	private static void writeCityModel(CityGMLChunkWriter writer, CityModel cModel) {
-		if (writer != null) {
-			for (ADEProperty genEle : cModel.getADEProperties()) {
-				writer.getCityModelInfo().addADEProperty(genEle);
-			}
-		}
-	}
-
-	private static void writeAbstractCityObject(CityGMLChunkWriter writer, AbstractCityObject ag)
-			throws CityGMLWriteException {
-		if (writer != null) {
-			writer.writeMember(ag);
-		}
-	}
-
-	private static CityGMLChunkWriter createCityModelWriter(String outputFile, CityGMLReader reader)
-			throws CityGMLWriteException {
-		if (outputFile == null) {
-			return null;
-		}
-		CityGMLContext gmlContext = CityGmlParser.getContext();
-		CityGMLVersion version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI());
-		CityGMLOutputFactory factory = gmlContext.createCityGMLOutputFactory(version);
-		CityGMLChunkWriter writer = factory.createCityGMLChunkWriter(new File(outputFile),
-				StandardCharsets.UTF_8.name());
-		writer.withPrefix("qual", QualityADEModule.NAMESPACE_URI);
-		writer.withSchemaLocation(QualityADEModule.NAMESPACE_URI, QualityADEModule.NAMESPACE_URI + "/qualityAde.xsd");
-		writer.withIndent("  ");
-		writer.withDefaultPrefixes();
-		writer.withDefaultSchemaLocations();
-		return writer;
-	}
-
-	private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, Path file,
-			CityGMLInputFactory inputFactory, ObservedInputStream ois, boolean verbose) throws CityGMLReadException {
-		return readAndKeepModel(new Citygml3FeatureMapper(config, file), inputFactory, ois, verbose);
-	}
-
-	private static CityDoctorModel readAndKeepModel(Citygml3FeatureMapper mapper, CityGMLInputFactory inputFactory,
-													ObservedInputStream ois, boolean verbose) throws CityGMLReadException{
-		try (CityGMLReader reader = inputFactory.createCityGMLReader(ois)) {
-			CityGMLVersion version = null;
-			// model is read in chunked mode
-			// object members are replaced by href in model
-			// need to remove the refs and re-add unparsed objects
-			List<AbstractCityObject> acos = new ArrayList<>();
-			while (reader.hasNext()) {
-				AbstractFeature chunk = reader.next();
-				version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI());
-				if (chunk instanceof CityModel cModel) {
-					cModel.setCityObjectMembers(null);
-					mapper.setCityModel(cModel);
-					mapper.setCityGMLVersion(version);
-				} else if (chunk instanceof AbstractCityObject aco) {
-					acos.add(aco);
-					aco.accept(mapper);
-				}
-			}
-
-			if (mapper.getModel().getCityModel() == null) {
-				// file does not contain a city model?
-				// create it for now
-				mapper.setCityModel(new CityModel());
-			}
-			CityModel cModel = mapper.getModel().getCityModel();
-
-			// remove those that should have been parsed
-			List<AbstractCityObject> parsedCityObjects = mapper.getModel().createFeatureStream()
-					.map(CityObject::getGmlObject).toList();
-			acos.removeAll(parsedCityObjects);
-			// re-add all not parsed objects
-			for (AbstractCityObject aco : acos) {
-				cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco));
-			}
-			if (logger.isInfoEnabled() && verbose) {
-				logger.info(Localization.getText("CityGmlParser.parsedObjects"),
-						mapper.getModel().getNumberOfFeatures());
-			}
-			mapper.setCityGMLVersion(version);
-			return mapper.getModel();
-		}
-	}
-
-	private static void parseEpsgCodeFromFile(Path file, ParserConfiguration config) throws CityGmlParseException {
-		try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file.toFile()))) {
-			parseEpsgCodeFromStream(bis, config);
-		} catch (ParserConfigurationException | SAXException | IOException e) {
-			throw new CityGmlParseException("Failed to read CityGML file", e);
-		}
-	}
-
-	private static void parseEpsgCodeFromStream(InputStream is, ParserConfiguration config)
-			throws ParserConfigurationException, SAXException {
-		SAXParser parser = FACTORY.newSAXParser();
-		CityGmlHandler handler = new CityGmlHandler();
-		try {
-			parser.parse(new InputSource(is), handler);
-		} catch (EnvelopeFoundException e) {
-			try {
-				parseCoordinateSystem(config, handler);
-			} catch (Exception e2) {
-				logEpsgParseError(e2);
-			}
-		} catch (Exception e) {
-			logEpsgParseError(e);
-		}
-	}
-
-	private static void parseEpsgCodeFromBuffer(byte[] buffer, ParserConfiguration config)
-			throws ParserConfigurationException, SAXException {
-		InputStream is = new ByteArrayInputStream(buffer);
-		SAXParser parser = FACTORY.newSAXParser();
-		CityGmlHandler handler = new CityGmlHandler();
-		try {
-			parser.parse(new InputSource(is), handler);
-		} catch (EnvelopeFoundException e) {
-			try {
-				parseCoordinateSystem(config, handler);
-
-			} catch (Exception e2) {
-				logEpsgParseError(e2);
-			}
-		}catch (SAXParseException spe){
-			// suppress XML document structure warning
-			if (!spe.getMessage().matches("XML document structures must start and end within the same entity.")){
-				logEpsgParseError(spe);
-			}
-		}catch (Exception e) {
-			logEpsgParseError(e);
-		}
-	}
-
-	private static void logEpsgParseError(Exception e){
-		logger.debug("Exception while parsing for EPSG code", e);
-		if (logger.isWarnEnabled()) {
-			logger.warn(Localization.getText("CityGmlParser.noEPSG"));
-		}
-	}
-
-	private static void parseCoordinateSystem(ParserConfiguration config, CityGmlHandler handler) {
-		if (handler.getEpsg() == null) {
-			return;
-		}
-		CoordinateReferenceSystem crs = crsFromSrsName(handler.getEpsg());
-		if (crs == null) {
-			// could not find a coordinate system for srsName
-			// assuming metric system
-			return;
-		}
-		if (crs.getProjection().getUnits() == Units.METRES) {
-			// coordinate system is in meters, do not convert
-			if (logger.isInfoEnabled()) {
-				logger.info(Localization.getText("CityGmlParser.noConversionNeeded"));
-			}
-			return;
-		}
-		parseMeterConversion(config, crs);
-		Vector3d low = handler.getLowerCorner();
-		Vector3d up = handler.getUpperCorner();
-		double centerLong = low.getX() + ((up.getX() - low.getX()) / 2);
-		double centerLat = low.getY() + ((up.getY() - low.getY()) / 2);
-		if (!crs.getName().equals(WGS_84)) {
-			// need to convert coordinates first to WGS84, then find UTM Zone
-			CoordinateReferenceSystem wgs84 = crsFromSrsName(WGS_84);
-			ProjCoordinate p1 = new ProjCoordinate();
-			p1.setValue(centerLong, centerLat);
-			ProjCoordinate p2 = new ProjCoordinate();
-			BasicCoordinateTransform bct = new BasicCoordinateTransform(crs, wgs84);
-			bct.transform(p1, p2);
-			centerLong = p2.x;
-			centerLat = p2.y;
-		}
-		int zone = (int) (31 + Math.round(centerLong / 6));
-		CoordinateReferenceSystem utm;
-		if (centerLat < 0) {
-			// south
-			logger.info("Converting coordiante system to UTM zone {}S", zone);
-			utm = CRS_FACTORY.createFromParameters("UTM", "+proj=utm +ellps=WGS84 +units=m +zone=" + zone + " +south");
-		} else {
-			// north
-			logger.info("Converting coordiante system to UTM zone {}N", zone);
-			utm = CRS_FACTORY.createFromParameters("UTM", "+proj=utm +ellps=WGS84 +units=m +zone=" + zone);
-		}
-		config.setCoordinateSystem(crs, utm);
-	}
-
-	private static void parseMeterConversion(ParserConfiguration config, CoordinateReferenceSystem crs) {
-		Projection projection = crs.getProjection();
-		double fromMetres = projection.getFromMetres();
-		if (fromMetres > 0) {
-			// also transform height information
-			config.setFromMeters(fromMetres);
-		} else {
-			config.setFromMeters(1.0);
-		}
-	}
-
-	/**
-	 * The srsName (The name by which this reference system is identified) inside
-	 * the CityGML file can have multiple formats. This method tries to parse the
-	 * string and detect the corresponding reference system. If it is found, it
-	 * returns a proj4j.CoordinateReferenceSystem. It throws an
-	 * IllegalArgumentException otherwise.
-	 * 
-	 * This method should be able to parse any EPSG id : e.g. "EPSG:1234". German
-	 * Citygmls might also have "DE_DHDN_3GK3" or "ETRS89_UTM32" as srsName, so
-	 * those are also included. It isn't guaranteed that those formats are correctly
-	 * parsed, though.
-	 * 
-	 * The EPSG ids and parameters are defined in resources ('nad/epsg') inside
-	 * proj4j-0.1.0.jar. Some EPSG ids are missing though, e.g. 7415
-	 * 
-	 * @param srsName
-	 * @return CoordinateReferenceSystem
-	 */
-	private static CoordinateReferenceSystem crsFromSrsName(String srsName) {
-		srsName = srsName.trim();
-		Matcher mEPSG = P_EPSG.matcher(srsName);
-		if (mEPSG.find()) {
-			if ("EPSG:4979".contentEquals(srsName)) {
-				srsName = "EPSG:4236";
-			} else if ("EPSG:7415".contentEquals(srsName)) {
-				return CRS_FACTORY.createFromParameters("EPSG:7415",
-						"+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs");
-			}
-			return CRS_FACTORY.createFromName(srsName);
-		}
-
-		Matcher mOGC = P_OGC.matcher(srsName);
-		if (mOGC.find()) {
-			return CRS_FACTORY.createFromName("EPSG:" + mOGC.group(1));
-		}
-		Matcher mOGC2 = P_OGC2.matcher(srsName);
-		if (mOGC2.find()) {
-			return CRS_FACTORY.createFromName("EPSG:" + mOGC2.group(1));
-		}
-		Matcher mURN = P_URN.matcher(srsName);
-		// NOTE: Could use a HashMap if the switch/case becomes too long.
-		if (mURN.find()) {
+    private static void startReadingCityGmlFile(Path file, ParserConfiguration config, ProgressListener l,
+                                                CityGmlConsumer cityObjectConsumer, String outputFile) {
+        try (ObservedInputStream ois = new ObservedInputStream(file.toFile())) {
+            if (l != null) {
+                ois.addListener(l::updateProgress);
+            }
+            readAndDiscardFeatures(file, config, ois, cityObjectConsumer, outputFile);
+        } catch (IOException | CityGMLReadException e) {
+            logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage());
+            logger.catching(Level.ERROR, e);
+        }
+    }
+
+    private static void readAndDiscardFeatures(Path file, ParserConfiguration config, ObservedInputStream ois,
+                                               CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
+        Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, file);
+        readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile);
+
+    }
+
+    private static void startReadingCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l,
+                                                    CityGmlConsumer cityObjectConsumer, String outputFile) {
+        try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry);
+             ObservedInputStream ois = new ObservedInputStream(entryFile.getInputStream(), entry.getFileSize())) {
+            if (l != null) {
+                ois.addListener(l::updateProgress);
+            }
+            streamAndDiscardFeatures(entry, config, ois, cityObjectConsumer, outputFile);
+        } catch (IOException | CityGMLReadException e) {
+            logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage());
+            logger.catching(Level.ERROR, e);
+        }
+    }
+
+    private static void streamAndDiscardFeatures(CityGmlZipEntry entry, ParserConfiguration config, ObservedInputStream ois,
+                                                 CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
+        Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, entry);
+        readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile);
+    }
+
+    private static void readAndDiscardModel(Citygml3FeatureMapper mapper, ObservedInputStream ois,
+                                            CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
+        getContext();
+        CityGMLInputFactory inputFactory = context.createCityGMLInputFactory()
+                .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
+        CityGMLChunkWriter writer = null;
+        try (CityGMLReader reader = inputFactory.createCityGMLReader(ois)) {
+
+            CityDoctorModel model = mapper.getModel();
+            boolean isInitialized = false;
+            while (reader.hasNext()) {
+                AbstractFeature chunk = reader.next();
+                if (writer == null) {
+                    writer = createCityModelWriter(outputFile, reader);
+                }
+                if (!isInitialized && writer != null && reader.getParentInfo() != null
+                        && reader.getParentInfo().getTypeName().getLocalPart().equals("CityModel")) {
+                    FeatureInfo parentInfo = reader.getParentInfo();
+                    writer.withCityModelInfo(parentInfo);
+                    isInitialized = true;
+                }
+                if (chunk instanceof AbstractCityObject ag) {
+                    ag.accept(mapper);
+                    drainCityModel(model, cityObjectConsumer);
+                    writeAbstractCityObject(writer, ag);
+                } else if (chunk instanceof CityModel cModel) {
+                    cModel.setCityObjectMembers(null);
+                    mapper.setCityModel(cModel);
+                    cityObjectConsumer.accept(cModel);
+                    writeCityModel(writer, cModel);
+                } else if (writer != null) {
+                    writer.writeMember(chunk);
+                }
+            }
+            // end of stream
+            logger.debug("End of gml file stream");
+        } catch (CityGMLReadException e) {
+            logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage(), e);
+        } catch (CityGMLWriteException e) {
+            logger.error(Localization.getText("CityGmlParser.errorWritingGmlFile"), e.getMessage(), e);
+        } finally {
+            if (writer != null) {
+                try {
+                    writer.close();
+                } catch (CityGMLWriteException e) {
+                    // ignore
+                }
+            }
+        }
+    }
+
+    private static void writeCityModel(CityGMLChunkWriter writer, CityModel cModel) {
+        if (writer != null) {
+            for (ADEProperty genEle : cModel.getADEProperties()) {
+                writer.getCityModelInfo().addADEProperty(genEle);
+            }
+        }
+    }
+
+    private static void writeAbstractCityObject(CityGMLChunkWriter writer, AbstractCityObject ag)
+            throws CityGMLWriteException {
+        if (writer != null) {
+            writer.writeMember(ag);
+        }
+    }
+
+    private static CityGMLChunkWriter createCityModelWriter(String outputFile, CityGMLReader reader)
+            throws CityGMLWriteException {
+        if (outputFile == null) {
+            return null;
+        }
+        CityGMLContext gmlContext = CityGmlParser.getContext();
+        CityGMLVersion version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI());
+        CityGMLOutputFactory factory = gmlContext.createCityGMLOutputFactory(version);
+        CityGMLChunkWriter writer = factory.createCityGMLChunkWriter(new File(outputFile),
+                StandardCharsets.UTF_8.name());
+        writer.withPrefix("qual", QualityADEModule.NAMESPACE_URI);
+        writer.withSchemaLocation(QualityADEModule.NAMESPACE_URI, QualityADEModule.NAMESPACE_URI + "/qualityAde.xsd");
+        writer.withIndent("  ");
+        writer.withDefaultPrefixes();
+        writer.withDefaultSchemaLocations();
+        return writer;
+    }
+
+    private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, Path file,
+                                                       CityGMLInputFactory inputFactory, ObservedInputStream ois, boolean verbose) throws CityGMLReadException {
+        return readAndKeepModel(new Citygml3FeatureMapper(config, file), inputFactory, ois, verbose);
+    }
+
+    private static CityDoctorModel readAndKeepModel(Citygml3FeatureMapper mapper, CityGMLInputFactory inputFactory,
+                                                    ObservedInputStream ois, boolean verbose) throws CityGMLReadException {
+        try (CityGMLReader reader = inputFactory.createCityGMLReader(ois)) {
+            CityGMLVersion version = null;
+            // model is read in chunked mode
+            // object members are replaced by href in model
+            // need to remove the refs and re-add unparsed objects
+            List<AbstractCityObject> acos = new ArrayList<>();
+            while (reader.hasNext()) {
+                AbstractFeature chunk = reader.next();
+                version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI());
+                if (chunk instanceof CityModel cModel) {
+                    cModel.setCityObjectMembers(null);
+                    mapper.setCityModel(cModel);
+                    mapper.setCityGMLVersion(version);
+                } else if (chunk instanceof AbstractCityObject aco) {
+                    acos.add(aco);
+                    aco.accept(mapper);
+                }
+            }
+
+            if (mapper.getModel().getCityModel() == null) {
+                // file does not contain a city model?
+                // create it for now
+                mapper.setCityModel(new CityModel());
+            }
+            CityModel cModel = mapper.getModel().getCityModel();
+
+            // remove those that should have been parsed
+            List<AbstractCityObject> parsedCityObjects = mapper.getModel().createFeatureStream()
+                    .map(CityObject::getGmlObject).toList();
+            acos.removeAll(parsedCityObjects);
+            // re-add all not parsed objects
+            for (AbstractCityObject aco : acos) {
+                cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco));
+            }
+            if (logger.isInfoEnabled() && verbose) {
+                logger.info(Localization.getText("CityGmlParser.parsedObjects"),
+                        mapper.getModel().getNumberOfFeatures());
+            }
+            mapper.setCityGMLVersion(version);
+            return mapper.getModel();
+        }
+    }
+
+    private static void parseEpsgCodeFromFile(Path file, ParserConfiguration config) throws CityGmlParseException {
+        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file.toFile()))) {
+            parseEpsgCodeFromStream(bis, config);
+        } catch (ParserConfigurationException | SAXException | IOException e) {
+            throw new CityGmlParseException("Failed to read CityGML file", e);
+        }
+    }
+
+    private static void parseEpsgCodeFromStream(InputStream is, ParserConfiguration config)
+            throws ParserConfigurationException, SAXException {
+        SAXParser parser = FACTORY.newSAXParser();
+        CityGmlHandler handler = new CityGmlHandler();
+        try {
+            parser.parse(new InputSource(is), handler);
+        } catch (EnvelopeFoundException e) {
+            try {
+                parseCoordinateSystem(config, handler);
+            } catch (Exception e2) {
+                logEpsgParseError(e2);
+            }
+        } catch (Exception e) {
+            logEpsgParseError(e);
+        }
+    }
+
+    private static void parseEpsgCodeFromBuffer(byte[] buffer, ParserConfiguration config)
+            throws ParserConfigurationException, SAXException {
+        InputStream is = new ByteArrayInputStream(buffer);
+        SAXParser parser = FACTORY.newSAXParser();
+        CityGmlHandler handler = new CityGmlHandler();
+        try {
+            parser.parse(new InputSource(is), handler);
+        } catch (EnvelopeFoundException e) {
+            try {
+                parseCoordinateSystem(config, handler);
+
+            } catch (Exception e2) {
+                logEpsgParseError(e2);
+            }
+        } catch (SAXParseException spe) {
+            // suppress XML document structure warning
+            if (!spe.getMessage().matches("XML document structures must start and end within the same entity.")) {
+                logEpsgParseError(spe);
+            }
+        } catch (Exception e) {
+            logEpsgParseError(e);
+        }
+    }
+
+    private static void logEpsgParseError(Exception e) {
+        logger.debug("Exception while parsing for EPSG code", e);
+        if (logger.isWarnEnabled()) {
+            logger.warn(Localization.getText("CityGmlParser.noEPSG"));
+        }
+    }
+
+    private static void parseCoordinateSystem(ParserConfiguration config, CityGmlHandler handler) {
+        if (handler.getEpsg() == null) {
+            return;
+        }
+        CoordinateReferenceSystem crs = crsFromSrsName(handler.getEpsg());
+        if (crs == null) {
+            // could not find a coordinate system for srsName
+            // assuming metric system
+            return;
+        }
+        if (crs.getProjection().getUnits() == Units.METRES) {
+            // coordinate system is in meters, do not convert
+            if (logger.isInfoEnabled()) {
+                logger.info(Localization.getText("CityGmlParser.noConversionNeeded"));
+            }
+            return;
+        }
+        parseMeterConversion(config, crs);
+        Vector3d low = handler.getLowerCorner();
+        Vector3d up = handler.getUpperCorner();
+        double centerLong = low.getX() + ((up.getX() - low.getX()) / 2);
+        double centerLat = low.getY() + ((up.getY() - low.getY()) / 2);
+        if (!crs.getName().equals(WGS_84)) {
+            // need to convert coordinates first to WGS84, then find UTM Zone
+            CoordinateReferenceSystem wgs84 = crsFromSrsName(WGS_84);
+            ProjCoordinate p1 = new ProjCoordinate();
+            p1.setValue(centerLong, centerLat);
+            ProjCoordinate p2 = new ProjCoordinate();
+            BasicCoordinateTransform bct = new BasicCoordinateTransform(crs, wgs84);
+            bct.transform(p1, p2);
+            centerLong = p2.x;
+            centerLat = p2.y;
+        }
+        int zone = (int) (31 + Math.round(centerLong / 6));
+        CoordinateReferenceSystem utm;
+        if (centerLat < 0) {
+            // south
+            logger.info("Converting coordiante system to UTM zone {}S", zone);
+            utm = CRS_FACTORY.createFromParameters("UTM", "+proj=utm +ellps=WGS84 +units=m +zone=" + zone + " +south");
+        } else {
+            // north
+            logger.info("Converting coordiante system to UTM zone {}N", zone);
+            utm = CRS_FACTORY.createFromParameters("UTM", "+proj=utm +ellps=WGS84 +units=m +zone=" + zone);
+        }
+        config.setCoordinateSystem(crs, utm);
+    }
+
+    private static void parseMeterConversion(ParserConfiguration config, CoordinateReferenceSystem crs) {
+        Projection projection = crs.getProjection();
+        double fromMetres = projection.getFromMetres();
+        if (fromMetres > 0) {
+            // also transform height information
+            config.setFromMeters(fromMetres);
+        } else {
+            config.setFromMeters(1.0);
+        }
+    }
+
+    /**
+     * The srsName (The name by which this reference system is identified) inside
+     * the CityGML file can have multiple formats. This method tries to parse the
+     * string and detect the corresponding reference system. If it is found, it
+     * returns a proj4j.CoordinateReferenceSystem. It throws an
+     * IllegalArgumentException otherwise.
+     * <p>
+     * This method should be able to parse any EPSG id : e.g. "EPSG:1234". German
+     * Citygmls might also have "DE_DHDN_3GK3" or "ETRS89_UTM32" as srsName, so
+     * those are also included. It isn't guaranteed that those formats are correctly
+     * parsed, though.
+     * <p>
+     * The EPSG ids and parameters are defined in resources ('nad/epsg') inside
+     * proj4j-0.1.0.jar. Some EPSG ids are missing though, e.g. 7415
+     *
+     * @param srsName
+     * @return CoordinateReferenceSystem
+     */
+    private static CoordinateReferenceSystem crsFromSrsName(String srsName) {
+        srsName = srsName.trim();
+        Matcher mEPSG = P_EPSG.matcher(srsName);
+        if (mEPSG.find()) {
+            if ("EPSG:4979".contentEquals(srsName)) {
+                srsName = "EPSG:4236";
+            } else if ("EPSG:7415".contentEquals(srsName)) {
+                return CRS_FACTORY.createFromParameters("EPSG:7415",
+                        "+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs");
+            }
+            return CRS_FACTORY.createFromName(srsName);
+        }
+
+        Matcher mOGC = P_OGC.matcher(srsName);
+        if (mOGC.find()) {
+            return CRS_FACTORY.createFromName("EPSG:" + mOGC.group(1));
+        }
+        Matcher mOGC2 = P_OGC2.matcher(srsName);
+        if (mOGC2.find()) {
+            return CRS_FACTORY.createFromName("EPSG:" + mOGC2.group(1));
+        }
+        Matcher mURN = P_URN.matcher(srsName);
+        // NOTE: Could use a HashMap if the switch/case becomes too long.
+        if (mURN.find()) {
             return switch (mURN.group(1)) {
                 case "DE_DHDN_3GK2" -> CRS_FACTORY.createFromName("EPSG:31466");
                 case "DE_DHDN_3GK3" -> CRS_FACTORY.createFromName("EPSG:31467");
@@ -676,59 +682,59 @@ public class CityGmlParser {
                 case "ETRS89_UTM32" -> CRS_FACTORY.createFromName("EPSG:25832");
                 default -> null;
             };
-		}
-		if (srsName.equals("http://www.opengis.net/def/crs/EPSG/0/6697")) {
-			return CRS_FACTORY.createFromParameters("EPSG:6697", "+proj=longlat +ellps=GRS80 +no_defs +axis=neu");
-		}
-		return null;
-	}
-
-	private static List<String> validateFile(CityGMLContext context, GMLValidationHandler handler, Path file)
-			throws CityGmlParseException {
-		if (handler == null) {
-			handler = new GMLValidationHandler();
-		}
-		try {
-			SchemaHandler schemaHandler = new ValidationSchemaHandler(context.getDefaultSchemaHandler());
+        }
+        if (srsName.equals("http://www.opengis.net/def/crs/EPSG/0/6697")) {
+            return CRS_FACTORY.createFromParameters("EPSG:6697", "+proj=longlat +ellps=GRS80 +no_defs +axis=neu");
+        }
+        return null;
+    }
+
+    private static List<String> validateFile(CityGMLContext context, GMLValidationHandler handler, Path file)
+            throws CityGmlParseException {
+        if (handler == null) {
+            handler = new GMLValidationHandler();
+        }
+        try {
+            SchemaHandler schemaHandler = new ValidationSchemaHandler(context.getDefaultSchemaHandler());
             readAdditionalSchemaDefinitions(context, file, schemaHandler);
-			Source[] schemas = schemaHandler.getSchemas();
-			SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-			schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-			Schema schema = schemaFactory.newSchema(schemas);
-			Validator validator = schema.newValidator();
-			validator.setErrorHandler(handler);
-			validator.validate(new StreamSource(file.toFile()));
-			return handler.getMessages();
-		} catch (SchemaHandlerException | SAXException | IOException e) {
-			throw new CityGmlParseException("Failed to validate CityGML file", e);
-		}
-	}
-
-	private static void readAdditionalSchemaDefinitions(CityGMLContext context, Path file, SchemaHandler schemaHandler)
-			throws CityGmlParseException {
-		try (XMLReader reader = XMLReaderFactory.newInstance(context.getXMLObjects())
-		        .withSchemaHandler(schemaHandler)
-		        .createReader(file)) {
-		    reader.nextTag();
-		} catch (Exception e) {
-		    throw new CityGmlParseException("Failed to read file " + file.toAbsolutePath() + ".", e);
-		}
-	}
-
-	private static void drainCityModel(CityDoctorModel model, CityGmlConsumer cityObjectConsumer) {
-		drainCityObjectList(model.getBuildings(), cityObjectConsumer);
-		drainCityObjectList(model.getBridges(), cityObjectConsumer);
-		drainCityObjectList(model.getVegetation(), cityObjectConsumer);
-		drainCityObjectList(model.getLand(), cityObjectConsumer);
-		drainCityObjectList(model.getTransportation(), cityObjectConsumer);
-		drainCityObjectList(model.getWater(), cityObjectConsumer);
-	}
-
-	private static void drainCityObjectList(List<? extends CityObject> objects, CityGmlConsumer cityObjectConsumer) {
-		for (CityObject co : objects) {
-			cityObjectConsumer.accept(co);
-		}
-		objects.clear();
-	}
+            Source[] schemas = schemaHandler.getSchemas();
+            SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+            schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+            Schema schema = schemaFactory.newSchema(schemas);
+            Validator validator = schema.newValidator();
+            validator.setErrorHandler(handler);
+            validator.validate(new StreamSource(file.toFile()));
+            return handler.getMessages();
+        } catch (SchemaHandlerException | SAXException | IOException e) {
+            throw new CityGmlParseException("Failed to validate CityGML file", e);
+        }
+    }
+
+    private static void readAdditionalSchemaDefinitions(CityGMLContext context, Path file, SchemaHandler schemaHandler)
+            throws CityGmlParseException {
+        try (XMLReader reader = XMLReaderFactory.newInstance(context.getXMLObjects())
+                .withSchemaHandler(schemaHandler)
+                .createReader(file)) {
+            reader.nextTag();
+        } catch (Exception e) {
+            throw new CityGmlParseException("Failed to read file " + file.toAbsolutePath() + ".", e);
+        }
+    }
+
+    private static void drainCityModel(CityDoctorModel model, CityGmlConsumer cityObjectConsumer) {
+        drainCityObjectList(model.getBuildings(), cityObjectConsumer);
+        drainCityObjectList(model.getBridges(), cityObjectConsumer);
+        drainCityObjectList(model.getVegetation(), cityObjectConsumer);
+        drainCityObjectList(model.getLand(), cityObjectConsumer);
+        drainCityObjectList(model.getTransportation(), cityObjectConsumer);
+        drainCityObjectList(model.getWater(), cityObjectConsumer);
+    }
+
+    private static void drainCityObjectList(List<? extends CityObject> objects, CityGmlConsumer cityObjectConsumer) {
+        for (CityObject co : objects) {
+            cityObjectConsumer.accept(co);
+        }
+        objects.clear();
+    }
 
 }
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java
index 5578165..9413aa3 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java
@@ -5,12 +5,14 @@ import de.hft.stuttgart.citydoctor2.utils.ArchivePacker;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.io.*;
-
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.Serial;
+import java.io.Serializable;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
-
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import java.util.zip.ZipInputStream;
@@ -32,8 +34,7 @@ public class CityGmlZipArchive implements Serializable {
         CityGmlZipArchive cgmlArchive = new CityGmlZipArchive(Path.of(zipFile));
         try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
             ZipEntry ze;
-            while ((ze = zis.getNextEntry()) != null )
-            {
+            while ((ze = zis.getNextEntry()) != null) {
                 if (ze.isDirectory()) {
                     continue;
                 }
@@ -49,9 +50,9 @@ public class CityGmlZipArchive implements Serializable {
         }
     }
 
-    public void mountArchive(ParserConfiguration config){
+    public void mountArchive(ParserConfiguration config) {
         try (ZipFile zip = new ZipFile(archivePath.toFile())) {
-            for (CityGmlZipEntry entry : entries){
+            for (CityGmlZipEntry entry : entries) {
                 entry.loadEntry(config);
             }
         } catch (IOException e) {
@@ -59,9 +60,9 @@ public class CityGmlZipArchive implements Serializable {
         }
     }
 
-      private CityGmlZipArchive(Path archivePath){
+    private CityGmlZipArchive(Path archivePath) {
         this.archivePath = archivePath;
-        this.archiveNameRE = archivePath.getFileName().toString().replace(".zip","") + File.separator;
+        this.archiveNameRE = archivePath.getFileName().toString().replace(".zip", "") + File.separator;
     }
 
     private void setEntries(List<CityGmlZipEntry> entries) {
@@ -69,16 +70,16 @@ public class CityGmlZipArchive implements Serializable {
         entries.forEach(e -> e.setArchive(this));
     }
 
-    public void exportToZipFile(String path)  {
+    public void exportToZipFile(String path) {
         ArchivePacker.packArchive(path, this);
     }
 
 
     public CityGmlZipEntry getEntry(String fileName) {
         fileName = stripArchivePath(fileName);
-        for(CityGmlZipEntry entry : entries){
+        for (CityGmlZipEntry entry : entries) {
             String entryName = stripArchivePath(entry.getFileName());
-            if(entryName.equals(fileName)){
+            if (entryName.equals(fileName)) {
                 return entry;
             }
         }
diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java
index c3383c0..7d6474b 100644
--- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java
+++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java
@@ -27,39 +27,39 @@ public class CityGmlZipEntry implements Serializable {
     private static final long MB = 1024 * 1024L;
     private ZipEntryErrorType errorType = null;
 
-    public static CityGmlZipEntry of(ZipEntry entry,CityGmlZipArchive parentArchive, ParserConfiguration config){
+    public static CityGmlZipEntry of(ZipEntry entry, CityGmlZipArchive parentArchive, ParserConfiguration config) {
         CityGmlZipEntry ze = CityGmlZipEntry.register(entry, parentArchive);
         ze.loadEntry(config);
         return ze;
     }
 
-    public void loadEntry(ParserConfiguration config){
-        if (decompressed){
+    public void loadEntry(ParserConfiguration config) {
+        if (decompressed) {
             return;
         }
-        if (errorType != null){
+        if (errorType != null) {
             logger.warn("Tried loading erroneous CityGmlZipEntry");
             return;
         }
-        try{
+        try {
             this.model = CityGmlParser.parseCityGmlZipEntry(this, config);
             this.decompressed = true;
         } catch (CityGmlParseException | InvalidGmlFileException e) {
             logger.error(e);
             this.errorType = ZipEntryErrorType.INVALID_CITY_GML_FILE;
-        } catch (IOException e){
+        } catch (IOException e) {
             logger.error(e);
             this.errorType = ZipEntryErrorType.IO_ERROR;
         }
     }
 
-    public static CityGmlZipEntry register(ZipEntry entry, CityGmlZipArchive parentArchive){
-        CityGmlZipEntry cgzEntry = new CityGmlZipEntry(entry, parentArchive,false);
-        try{
+    public static CityGmlZipEntry register(ZipEntry entry, CityGmlZipArchive parentArchive) {
+        CityGmlZipEntry cgzEntry = new CityGmlZipEntry(entry, parentArchive, false);
+        try {
             if (!cgzEntry.entrySizeWithinMemoryLimits()) {
                 cgzEntry.errorType = ZipEntryErrorType.EXCESSIVE_FILESIZE;
             }
-        } catch (IOException e){
+        } catch (IOException e) {
             logger.error(e);
             cgzEntry.errorType = ZipEntryErrorType.IO_ERROR;
         }
@@ -67,11 +67,11 @@ public class CityGmlZipEntry implements Serializable {
     }
 
     private boolean entrySizeWithinMemoryLimits() throws IOException {
-        long memoryLimit = (long) Math.ceil(((double) Runtime.getRuntime().maxMemory() / MB)*0.9);
+        long memoryLimit = (long) Math.ceil(((double) Runtime.getRuntime().maxMemory() / MB) * 0.9);
         if (fileSize == -1L) {
-            try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(this)){
+            try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(this)) {
                 long filesize = entryFile.getFileSize();
-                if (filesize != -1){
+                if (filesize != -1) {
                     this.fileSize = filesize;
                 } else {
                     return false;
@@ -83,9 +83,9 @@ public class CityGmlZipEntry implements Serializable {
         return memoryLimit > fileSize;
     }
 
-    protected CityGmlZipEntry(ZipEntry entry,CityGmlZipArchive parentArchive, boolean decompressed) {
+    protected CityGmlZipEntry(ZipEntry entry, CityGmlZipArchive parentArchive, boolean decompressed) {
         this.fileName = entry.getName();
-        if (entry.getSize() != -1){
+        if (entry.getSize() != -1) {
             this.fileSize = entry.getSize();
         }
         this.model = null;
@@ -93,15 +93,14 @@ public class CityGmlZipEntry implements Serializable {
         this.parentArchive = parentArchive;
     }
 
-    public void setArchive(CityGmlZipArchive archive){
+    public void setArchive(CityGmlZipArchive archive) {
         parentArchive = archive;
     }
 
-    public CityGmlZipArchive getArchive(){
+    public CityGmlZipArchive getArchive() {
         return parentArchive;
     }
 
-
     public String getFileName() {
         return fileName;
     }
@@ -118,7 +117,7 @@ public class CityGmlZipEntry implements Serializable {
         fileSize = size;
     }
 
-    public long getFileSize(){
+    public long getFileSize() {
         return fileSize;
     }
 }
diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java
index 8c0b41c..71a8d8e 100644
--- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java
+++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java
@@ -9,11 +9,14 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 public class ZipTest {
 
-    ParserConfiguration config = new ParserConfiguration(8,false);
+    ParserConfiguration config = new ParserConfiguration(8, false);
 
 
     @Test
@@ -25,8 +28,8 @@ public class ZipTest {
         checkMockArchive(cgmlArch);
     }
 
-    private void checkMockArchive(CityGmlZipArchive cgmlArch){
-        assertEquals(5,cgmlArch.getEntries().size());
+    private void checkMockArchive(CityGmlZipArchive cgmlArch) {
+        assertEquals(5, cgmlArch.getEntries().size());
         for (CityGmlZipEntry entry : cgmlArch.getEntries()) {
             assertNotNull(entry);
             assertTrue(entry.getFileName().matches("^mock[1-5].gml$"));
@@ -79,8 +82,8 @@ public class ZipTest {
     }
 
     @Test
-    public void testXMLValidation(){
-        ParserConfiguration valConfig = new ParserConfiguration(8,true);
+    public void testXMLValidation() {
+        ParserConfiguration valConfig = new ParserConfiguration(8, true);
         CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/validate.zip");
         assertNotNull(cgmlArch);
         cgmlArch.mountArchive(valConfig);
@@ -91,7 +94,7 @@ public class ZipTest {
 
 
     @Test
-    public void testImplicitParsing(){
+    public void testImplicitParsing() {
         CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/implicit.zip");
         assertNotNull(cgmlArch);
         cgmlArch.mountArchive(config);
diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
index f498e1c..e3cb538 100644
--- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
+++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
@@ -1,6 +1,6 @@
 /*-
  *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
- * 
+ *
  *  This file is part of CityDoctor2.
  *
  *  CityDoctor2 is free software: you can redistribute it and/or modify
@@ -18,41 +18,6 @@
  */
 package de.hft.stuttgart.citydoctor2.check;
 
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import javax.xml.XMLConstants;
-import javax.xml.transform.Result;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.stream.StreamSource;
-
-import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
-import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
 import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
 import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
 import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError;
@@ -78,6 +43,8 @@ import de.hft.stuttgart.citydoctor2.reporting.XmlValidationReporter;
 import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfReporter;
 import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfStreamReporter;
 import de.hft.stuttgart.citydoctor2.utils.Localization;
+import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
+import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile;
 import de.hft.stuttgart.quality.model.enums.RequirementId;
 import de.hft.stuttgart.quality.model.enums.TopLevelFeatureType;
 import de.hft.stuttgart.quality.model.properties.CheckingProperty;
@@ -88,309 +55,339 @@ import de.hft.stuttgart.quality.model.properties.RequirementProperty;
 import de.hft.stuttgart.quality.model.types.Checking;
 import de.hft.stuttgart.quality.model.types.Parameter;
 import de.hft.stuttgart.quality.model.types.ValidationPlan;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Stream;
 
 /**
  * The main container class for checking. It contains the logic for validation,
  * as well as contains the state of the checks performed.
- * 
- * @author Matthias Betz
  *
+ * @author Matthias Betz
  */
 public class Checker {
 
-	private static final Logger logger = LogManager.getLogger(Checker.class);
-
-	private ValidationConfiguration config;
-	private List<List<Check>> execLayers;
-
-	private List<Filter> includeFilters;
-	private List<Filter> excludeFilters;
-
-	private final Checks checkConfig;
-	private final CityDoctorModel model;
-
-	public Checker(CityDoctorModel model) {
-		this(ValidationConfiguration.loadStandardValidationConfig(), model);
-	}
-
-	public Checker(ValidationConfiguration config, CityDoctorModel model) {
-		this.model = model;
-		checkConfig = new Checks();
-		setValidationConfig(config);
-	}
-
-	public Checks getChecks() {
-		return checkConfig;
-	}
-
-	public CityDoctorModel getModel() {
-		return model;
-	}
-
-	/**
-	 * Write the xml report for the given CityDoctorModel. If no report location is
-	 * given or this checker has not validated anything, nothing is done.
-	 * 
-	 * @param xmlOutput the output file location for the XML report. Can be null.
-	 */
-	public void writeXmlReport(String xmlOutput) {
-		if (!model.isValidated() || xmlOutput == null) {
-			return;
-		}
-		File xmlFile = new File(xmlOutput);
-		if (xmlFile.getParentFile() != null) {
-			xmlFile.getParentFile().mkdirs();
-		}
-		Reporter reporter = new XmlValidationReporter();
-		try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(xmlFile.getAbsolutePath()))) {
-			reporter.writeReport(checkConfig, bos, model, config);
-		} catch (CheckReportWriteException | IOException e) {
-			logger.error(Localization.getText("Checker.failXml"), e);
-		}
-	}
-
-	public void writePdfReport(String pdfOutput) {
-		if (!model.isValidated() || pdfOutput == null) {
-			return;
-		}
-		File pdfFile = new File(pdfOutput);
-		if (pdfFile.getParentFile() != null) {
-			pdfFile.getParentFile().mkdirs();
-		}
-		Reporter reporter = new PdfReporter();
-		try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pdfFile.getAbsolutePath()))) {
-			reporter.writeReport(checkConfig, bos, model, config);
-		} catch (IOException | CheckReportWriteException e) {
-			logger.error(Localization.getText("Checker.failPdf"), e);
-		}
-	}
-
-	public void runChecks() {
-		runChecks((ProgressListener) null);
-	}
-
-	public void runChecks(String xmlOutput) {
-		runChecks();
-		writeXmlReport(xmlOutput);
-	}
-
-	public void runChecks(String xmlOutput, String pdfOutput) {
-		runChecks();
-		writeXmlReport(xmlOutput);
-		writePdfReport(pdfOutput);
-	}
-
-	public void runChecks(String xmlOutput, String pdfOutput, ProgressListener l) {
-		runChecks(l);
-		writeXmlReport(xmlOutput);
-		writePdfReport(pdfOutput);
-	}
-
-	public void runChecks(ProgressListener l) {
-		if (config == null) {
-			config = ValidationConfiguration.loadStandardValidationConfig();
-		}
-		checkCityModel(model, l);
-		if (logger.isInfoEnabled()) {
-			logger.info(Localization.getText("Checker.checksFinished"));
-		}
-		SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, model.getFile());
-		if (handler != null) {
-			handleSchematronResults(handler);
-		}
-		model.setValidated(createValidationPlan());
-	}
-
-	private void handleSchematronResults(SvrlContentHandler handler) {
-		model.addGlobalErrors(handler.getGeneralErrors());
-		Map<String, CityObject> featureMap = new HashMap<>();
-		model.createFeatureStream().forEach(f -> featureMap.put(f.getGmlId().getGmlString(), f));
-		handler.getFeatureErrors().forEach((k, v) -> {
-			if (k.trim().isEmpty()) {
-				// missing gml id, ignore?
-				return;
-			}
-			CityObject co = featureMap.get(k);
-			if (co == null) {
-				// gml id reported by schematron was not found, add to general errors
-				for (SchematronError se : v) {
-					model.addGlobalError(se);
-				}
-			} else {
-				handleSchematronErrorsForCityObject(v, co);
-			}
-		});
-	}
-
-	public static void handleSchematronErrorsForCityObject(List<SchematronError> v, CityObject co) {
-		int count = 0;
-		for (SchematronError se : v) {
-			CheckError err;
-			if (AttributeMissingError.ID.getIdString().equals(se.getErrorIdString())) {
-				err = new AttributeMissingError(co, se.getChildId(), se.getNameOfAttribute());
-			} else if (AttributeValueWrongError.ID.getIdString().equals(se.getErrorIdString())) {
-				err = new AttributeValueWrongError(co, se.getChildId(), se.getNameOfAttribute());
-			} else if (AttributeInvalidError.ID.getIdString().equals(se.getErrorIdString())) {
-				err = new AttributeInvalidError(co, se.getChildId(), se.getNameOfAttribute());
-			} else {
-				throw new IllegalStateException(
-						"Unknown error ID was given in schematron file: " + se.getErrorIdString());
-			}
-			co.addCheckResult(new CheckResult(new CheckId("SchematronCheck " + count), ResultStatus.ERROR, err));
-			count++;
-		}
-	}
-
-	ValidationPlan createValidationPlan() {
-		ValidationPlan plan = new ValidationPlan();
-		de.hft.stuttgart.quality.model.types.Filter filter = createFilter();
-		plan.setFilter(new FilterProperty(filter));
-
-		Map<String, de.hft.stuttgart.citydoctor2.check.Requirement> reqs = Checks.getAvailableRequirements();
-		for (Entry<String, RequirementConfiguration> e : config.getRequirements().entrySet()) {
-			RequirementId reqId = mapToRequirement(e.getKey());
-			if (reqId == null) {
-				continue;
-			}
-			de.hft.stuttgart.quality.model.types.Requirement req = new de.hft.stuttgart.quality.model.types.Requirement();
-			req.setRequirementType(reqId);
-			req.setEnabled(e.getValue().isEnabled());
-			plan.getRequirements().add(new RequirementProperty(req));
-			Map<String, String> parameters = e.getValue().getParameters();
-			if (parameters != null) {
-				for (Entry<String, String> param : parameters.entrySet()) {
-					Parameter p = new Parameter();
-					DefaultParameter defaultP = getDefaultParameter(e.getKey(), reqs, param.getKey());
-					if (defaultP != null) {
-						p.setUom(defaultP.getUnitType().getGmlRepresentation());
-					}
-					p.setName(param.getKey());
-					p.setValue(param.getValue());
-					req.getParameters().add(new ParameterProperty(p));
-				}
-			}
-		}
-
-		de.hft.stuttgart.quality.model.types.Requirement missing = new de.hft.stuttgart.quality.model.types.Requirement();
-		missing.setRequirementType(RequirementId.R_SE_ATTRIBUTES_EXISTING);
-		de.hft.stuttgart.quality.model.types.Requirement correct = new de.hft.stuttgart.quality.model.types.Requirement();
-		correct.setRequirementType(RequirementId.R_SE_ATTRIBUTES_CORRECT);
-		missing.setEnabled(config.getSchematronFilePath() != null);
-		correct.setEnabled(config.getSchematronFilePath() != null);
-		plan.getRequirements().add(new RequirementProperty(missing));
-		plan.getRequirements().add(new RequirementProperty(correct));
-
-		Parameter numRounding = new Parameter();
-		numRounding.setName("numberOfRoundingPlaces");
-		numRounding.setValue("" + config.getNumberOfRoundingPlaces());
-		Parameter minVertexDistance = new Parameter();
-		minVertexDistance.setName("minVertexDistance");
-		minVertexDistance.setUom("m");
-		minVertexDistance.setValue("" + config.getMinVertexDistance());
-		Parameter schematronFile = new Parameter();
-		schematronFile.setName("schematronFile");
-		schematronFile.setValue(config.getSchematronFilePath());
-		de.hft.stuttgart.quality.model.types.GlobalParameters globParams = new de.hft.stuttgart.quality.model.types.GlobalParameters();
-		plan.setGlobalParameters(new GlobalParametersProperty(globParams));
-		globParams.getParameters().add(new ParameterProperty(numRounding));
-		globParams.getParameters().add(new ParameterProperty(minVertexDistance));
-		globParams.getParameters().add(new ParameterProperty(schematronFile));
-		return plan;
-	}
-
-	private DefaultParameter getDefaultParameter(String reqKey,
-			Map<String, de.hft.stuttgart.citydoctor2.check.Requirement> reqs, String paramName) {
-		de.hft.stuttgart.citydoctor2.check.Requirement requirement = reqs.get(reqKey);
-		if (requirement != null) {
-			for (DefaultParameter param : requirement.getDefaultParameter()) {
-				if (param.getName().equals(paramName)) {
-					return param;
-				}
-			}
-		}
-		return null;
-	}
-
-	private de.hft.stuttgart.quality.model.types.Filter createFilter() {
-		var filter = new de.hft.stuttgart.quality.model.types.Filter();
-		handleInputFilter(filter);
-		if (excludeFilters != null) {
-			for (Filter f : excludeFilters) {
-				if (f instanceof TypeFilter tf) {
-					FeatureType type = tf.getType();
-					TopLevelFeatureType tlft = mapToTopLevelFeatureType(type);
-					if (tlft == null) {
-						continue;
-					}
-					removeFilter(tlft, filter);
-				}
-			}
-		}
-		return filter;
-	}
-
-	private void handleInputFilter(de.hft.stuttgart.quality.model.types.Filter filter) {
-		if (includeFilters == null || includeFilters.isEmpty()) {
-			// no filter means, use all
-			addAllFilters(filter);
-		} else {
-			for (Filter f : includeFilters) {
-				if (f instanceof TypeFilter tf) {
-					FeatureType type = tf.getType();
-					TopLevelFeatureType tlft = mapToTopLevelFeatureType(type);
-					if (tlft == null) {
-						continue;
-					}
-					Checking c = new Checking();
-					c.setFeatureType(tlft);
-					filter.getChecking().add(new CheckingProperty(c));
-				}
-			}
-			if (filter.getChecking().isEmpty()) {
-				// this happens if no type include filter was used
-				// it is possible only single objects were tested then
-				// so include everything
-				addAllFilters(filter);
-			}
-		}
-	}
-
-	private void addAllFilters(de.hft.stuttgart.quality.model.types.Filter filter) {
-		Checking buildingChecking = new Checking();
-		buildingChecking.setFeatureType(TopLevelFeatureType.BUILDING);
-		filter.getChecking().add(new CheckingProperty(buildingChecking));
-
-		Checking bridgeChecking = new Checking();
-		bridgeChecking.setFeatureType(TopLevelFeatureType.BRIDGE);
-		filter.getChecking().add(new CheckingProperty(bridgeChecking));
-
-		Checking landChecking = new Checking();
-		landChecking.setFeatureType(TopLevelFeatureType.LAND);
-		filter.getChecking().add(new CheckingProperty(landChecking));
-
-		Checking transportationChecking = new Checking();
-		transportationChecking.setFeatureType(TopLevelFeatureType.TRANSPORTATION);
-		filter.getChecking().add(new CheckingProperty(transportationChecking));
-
-		Checking vegetationChecking = new Checking();
-		vegetationChecking.setFeatureType(TopLevelFeatureType.VEGETATION);
-		filter.getChecking().add(new CheckingProperty(vegetationChecking));
-
-		Checking waterChecking = new Checking();
-		waterChecking.setFeatureType(TopLevelFeatureType.WATER);
-		filter.getChecking().add(new CheckingProperty(waterChecking));
-	}
-
-	private void removeFilter(TopLevelFeatureType tlft, de.hft.stuttgart.quality.model.types.Filter filter) {
-		for (CheckingProperty c : filter.getChecking()) {
-			if (c.getObject().getFeatureType().equals(tlft)) {
-				filter.getChecking().remove(c);
-				return;
-			}
-		}
-	}
-
-	private TopLevelFeatureType mapToTopLevelFeatureType(FeatureType type) {
+    private static final Logger logger = LogManager.getLogger(Checker.class);
+
+    private ValidationConfiguration config;
+    private List<List<Check>> execLayers;
+
+    private List<Filter> includeFilters;
+    private List<Filter> excludeFilters;
+
+    private final Checks checkConfig;
+    private final CityDoctorModel model;
+
+    public Checker(CityDoctorModel model) {
+        this(ValidationConfiguration.loadStandardValidationConfig(), model);
+    }
+
+    public Checker(ValidationConfiguration config, CityDoctorModel model) {
+        this.model = model;
+        checkConfig = new Checks();
+        setValidationConfig(config);
+    }
+
+    public Checks getChecks() {
+        return checkConfig;
+    }
+
+    public CityDoctorModel getModel() {
+        return model;
+    }
+
+    /**
+     * Write the xml report for the given CityDoctorModel. If no report location is
+     * given or this checker has not validated anything, nothing is done.
+     *
+     * @param xmlOutput the output file location for the XML report. Can be null.
+     */
+    public void writeXmlReport(String xmlOutput) {
+        if (!model.isValidated() || xmlOutput == null) {
+            return;
+        }
+        File xmlFile = new File(xmlOutput);
+        if (xmlFile.getParentFile() != null) {
+            xmlFile.getParentFile().mkdirs();
+        }
+        Reporter reporter = new XmlValidationReporter();
+        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(xmlFile.getAbsolutePath()))) {
+            reporter.writeReport(checkConfig, bos, model, config);
+        } catch (CheckReportWriteException | IOException e) {
+            logger.error(Localization.getText("Checker.failXml"), e);
+        }
+    }
+
+    public void writePdfReport(String pdfOutput) {
+        if (!model.isValidated() || pdfOutput == null) {
+            return;
+        }
+        File pdfFile = new File(pdfOutput);
+        if (pdfFile.getParentFile() != null) {
+            pdfFile.getParentFile().mkdirs();
+        }
+        Reporter reporter = new PdfReporter();
+        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pdfFile.getAbsolutePath()))) {
+            reporter.writeReport(checkConfig, bos, model, config);
+        } catch (IOException | CheckReportWriteException e) {
+            logger.error(Localization.getText("Checker.failPdf"), e);
+        }
+    }
+
+    public void runChecks() {
+        runChecks((ProgressListener) null);
+    }
+
+    public void runChecks(String xmlOutput) {
+        runChecks();
+        writeXmlReport(xmlOutput);
+    }
+
+    public void runChecks(String xmlOutput, String pdfOutput) {
+        runChecks();
+        writeXmlReport(xmlOutput);
+        writePdfReport(pdfOutput);
+    }
+
+    public void runChecks(String xmlOutput, String pdfOutput, ProgressListener l) {
+        runChecks(l);
+        writeXmlReport(xmlOutput);
+        writePdfReport(pdfOutput);
+    }
+
+    public void runChecks(ProgressListener l) {
+        if (config == null) {
+            config = ValidationConfiguration.loadStandardValidationConfig();
+        }
+        checkCityModel(model, l);
+        if (logger.isInfoEnabled()) {
+            logger.info(Localization.getText("Checker.checksFinished"));
+        }
+        SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, model.getFile());
+        if (handler != null) {
+            handleSchematronResults(handler);
+        }
+        model.setValidated(createValidationPlan());
+    }
+
+    private void handleSchematronResults(SvrlContentHandler handler) {
+        model.addGlobalErrors(handler.getGeneralErrors());
+        Map<String, CityObject> featureMap = new HashMap<>();
+        model.createFeatureStream().forEach(f -> featureMap.put(f.getGmlId().getGmlString(), f));
+        handler.getFeatureErrors().forEach((k, v) -> {
+            if (k.trim().isEmpty()) {
+                // missing gml id, ignore?
+                return;
+            }
+            CityObject co = featureMap.get(k);
+            if (co == null) {
+                // gml id reported by schematron was not found, add to general errors
+                for (SchematronError se : v) {
+                    model.addGlobalError(se);
+                }
+            } else {
+                handleSchematronErrorsForCityObject(v, co);
+            }
+        });
+    }
+
+    public static void handleSchematronErrorsForCityObject(List<SchematronError> v, CityObject co) {
+        int count = 0;
+        for (SchematronError se : v) {
+            CheckError err;
+            if (AttributeMissingError.ID.getIdString().equals(se.getErrorIdString())) {
+                err = new AttributeMissingError(co, se.getChildId(), se.getNameOfAttribute());
+            } else if (AttributeValueWrongError.ID.getIdString().equals(se.getErrorIdString())) {
+                err = new AttributeValueWrongError(co, se.getChildId(), se.getNameOfAttribute());
+            } else if (AttributeInvalidError.ID.getIdString().equals(se.getErrorIdString())) {
+                err = new AttributeInvalidError(co, se.getChildId(), se.getNameOfAttribute());
+            } else {
+                throw new IllegalStateException(
+                        "Unknown error ID was given in schematron file: " + se.getErrorIdString());
+            }
+            co.addCheckResult(new CheckResult(new CheckId("SchematronCheck " + count), ResultStatus.ERROR, err));
+            count++;
+        }
+    }
+
+    ValidationPlan createValidationPlan() {
+        ValidationPlan plan = new ValidationPlan();
+        de.hft.stuttgart.quality.model.types.Filter filter = createFilter();
+        plan.setFilter(new FilterProperty(filter));
+
+        Map<String, de.hft.stuttgart.citydoctor2.check.Requirement> reqs = Checks.getAvailableRequirements();
+        for (Entry<String, RequirementConfiguration> e : config.getRequirements().entrySet()) {
+            RequirementId reqId = mapToRequirement(e.getKey());
+            if (reqId == null) {
+                continue;
+            }
+            de.hft.stuttgart.quality.model.types.Requirement req = new de.hft.stuttgart.quality.model.types.Requirement();
+            req.setRequirementType(reqId);
+            req.setEnabled(e.getValue().isEnabled());
+            plan.getRequirements().add(new RequirementProperty(req));
+            Map<String, String> parameters = e.getValue().getParameters();
+            if (parameters != null) {
+                for (Entry<String, String> param : parameters.entrySet()) {
+                    Parameter p = new Parameter();
+                    DefaultParameter defaultP = getDefaultParameter(e.getKey(), reqs, param.getKey());
+                    if (defaultP != null) {
+                        p.setUom(defaultP.getUnitType().getGmlRepresentation());
+                    }
+                    p.setName(param.getKey());
+                    p.setValue(param.getValue());
+                    req.getParameters().add(new ParameterProperty(p));
+                }
+            }
+        }
+
+        de.hft.stuttgart.quality.model.types.Requirement missing = new de.hft.stuttgart.quality.model.types.Requirement();
+        missing.setRequirementType(RequirementId.R_SE_ATTRIBUTES_EXISTING);
+        de.hft.stuttgart.quality.model.types.Requirement correct = new de.hft.stuttgart.quality.model.types.Requirement();
+        correct.setRequirementType(RequirementId.R_SE_ATTRIBUTES_CORRECT);
+        missing.setEnabled(config.getSchematronFilePath() != null);
+        correct.setEnabled(config.getSchematronFilePath() != null);
+        plan.getRequirements().add(new RequirementProperty(missing));
+        plan.getRequirements().add(new RequirementProperty(correct));
+
+        Parameter numRounding = new Parameter();
+        numRounding.setName("numberOfRoundingPlaces");
+        numRounding.setValue("" + config.getNumberOfRoundingPlaces());
+        Parameter minVertexDistance = new Parameter();
+        minVertexDistance.setName("minVertexDistance");
+        minVertexDistance.setUom("m");
+        minVertexDistance.setValue("" + config.getMinVertexDistance());
+        Parameter schematronFile = new Parameter();
+        schematronFile.setName("schematronFile");
+        schematronFile.setValue(config.getSchematronFilePath());
+        de.hft.stuttgart.quality.model.types.GlobalParameters globParams = new de.hft.stuttgart.quality.model.types.GlobalParameters();
+        plan.setGlobalParameters(new GlobalParametersProperty(globParams));
+        globParams.getParameters().add(new ParameterProperty(numRounding));
+        globParams.getParameters().add(new ParameterProperty(minVertexDistance));
+        globParams.getParameters().add(new ParameterProperty(schematronFile));
+        return plan;
+    }
+
+    private DefaultParameter getDefaultParameter(String reqKey,
+                                                 Map<String, de.hft.stuttgart.citydoctor2.check.Requirement> reqs, String paramName) {
+        de.hft.stuttgart.citydoctor2.check.Requirement requirement = reqs.get(reqKey);
+        if (requirement != null) {
+            for (DefaultParameter param : requirement.getDefaultParameter()) {
+                if (param.getName().equals(paramName)) {
+                    return param;
+                }
+            }
+        }
+        return null;
+    }
+
+    private de.hft.stuttgart.quality.model.types.Filter createFilter() {
+        var filter = new de.hft.stuttgart.quality.model.types.Filter();
+        handleInputFilter(filter);
+        if (excludeFilters != null) {
+            for (Filter f : excludeFilters) {
+                if (f instanceof TypeFilter tf) {
+                    FeatureType type = tf.getType();
+                    TopLevelFeatureType tlft = mapToTopLevelFeatureType(type);
+                    if (tlft == null) {
+                        continue;
+                    }
+                    removeFilter(tlft, filter);
+                }
+            }
+        }
+        return filter;
+    }
+
+    private void handleInputFilter(de.hft.stuttgart.quality.model.types.Filter filter) {
+        if (includeFilters == null || includeFilters.isEmpty()) {
+            // no filter means, use all
+            addAllFilters(filter);
+        } else {
+            for (Filter f : includeFilters) {
+                if (f instanceof TypeFilter tf) {
+                    FeatureType type = tf.getType();
+                    TopLevelFeatureType tlft = mapToTopLevelFeatureType(type);
+                    if (tlft == null) {
+                        continue;
+                    }
+                    Checking c = new Checking();
+                    c.setFeatureType(tlft);
+                    filter.getChecking().add(new CheckingProperty(c));
+                }
+            }
+            if (filter.getChecking().isEmpty()) {
+                // this happens if no type include filter was used
+                // it is possible only single objects were tested then
+                // so include everything
+                addAllFilters(filter);
+            }
+        }
+    }
+
+    private void addAllFilters(de.hft.stuttgart.quality.model.types.Filter filter) {
+        Checking buildingChecking = new Checking();
+        buildingChecking.setFeatureType(TopLevelFeatureType.BUILDING);
+        filter.getChecking().add(new CheckingProperty(buildingChecking));
+
+        Checking bridgeChecking = new Checking();
+        bridgeChecking.setFeatureType(TopLevelFeatureType.BRIDGE);
+        filter.getChecking().add(new CheckingProperty(bridgeChecking));
+
+        Checking landChecking = new Checking();
+        landChecking.setFeatureType(TopLevelFeatureType.LAND);
+        filter.getChecking().add(new CheckingProperty(landChecking));
+
+        Checking transportationChecking = new Checking();
+        transportationChecking.setFeatureType(TopLevelFeatureType.TRANSPORTATION);
+        filter.getChecking().add(new CheckingProperty(transportationChecking));
+
+        Checking vegetationChecking = new Checking();
+        vegetationChecking.setFeatureType(TopLevelFeatureType.VEGETATION);
+        filter.getChecking().add(new CheckingProperty(vegetationChecking));
+
+        Checking waterChecking = new Checking();
+        waterChecking.setFeatureType(TopLevelFeatureType.WATER);
+        filter.getChecking().add(new CheckingProperty(waterChecking));
+    }
+
+    private void removeFilter(TopLevelFeatureType tlft, de.hft.stuttgart.quality.model.types.Filter filter) {
+        for (CheckingProperty c : filter.getChecking()) {
+            if (c.getObject().getFeatureType().equals(tlft)) {
+                filter.getChecking().remove(c);
+                return;
+            }
+        }
+    }
+
+    private TopLevelFeatureType mapToTopLevelFeatureType(FeatureType type) {
         return switch (type) {
             case BRIDGE -> TopLevelFeatureType.BRIDGE;
             case BUILDING -> TopLevelFeatureType.BUILDING;
@@ -400,298 +397,298 @@ public class Checker {
             case WATER -> TopLevelFeatureType.WATER;
             default -> null;
         };
-	}
-
-	private RequirementId mapToRequirement(String requirementName) {
-		try {
-			return RequirementId.valueOf(requirementName);
-		} catch (IllegalArgumentException e) {
-			return null;
-		}
-	}
-
-	public ValidationConfiguration getConfig() {
-		return config;
-	}
-
-	public static SvrlContentHandler executeSchematronValidationIfAvailable(ValidationConfiguration config, File file) {
-		if (file == null || !file.exists()) {
-			return null;
-		}
-		try {
-			return executeSchematronValidationIfAvailable(config, new FileInputStream(file));
-		} catch (FileNotFoundException e) {
-			throw new UncheckedIOException(e);
-		}
-	}
-
-	public static SvrlContentHandler executeSchematronValidationIfAvailable(ValidationConfiguration config,
-			InputStream in) {
-		if (config.getSchematronFilePath() != null && !config.getSchematronFilePath().isEmpty()) {
-			if (logger.isInfoEnabled()) {
-				logger.info(Localization.getText("Checker.schematronValidation"));
-			}
-
-			try {
-				TransformerFactory transformerFactory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", Checker.class.getClassLoader());
-				transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
-				transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-
-				transformerFactory.setURIResolver((href, base) -> new StreamSource(Checker.class.getResourceAsStream(href)));
-				
-				Source dsdlXslSource = new StreamSource(Checker.class.getResourceAsStream("iso_dsdl_include.xsl"));
-				Transformer dsdlXslTransformer = transformerFactory.newTransformer(dsdlXslSource);
-				
-				DOMResult dsdlXslResult = new DOMResult();
-				dsdlXslTransformer.transform(new StreamSource(new File(config.getSchematronFilePath())), dsdlXslResult);
-			
-				Source abstractExpandXsl = new StreamSource(Checker.class.getResourceAsStream("iso_abstract_expand.xsl"));
-				Transformer abstractExpandTransformer = transformerFactory.newTransformer(abstractExpandXsl);
-				
-				DOMResult abstractExpandResult = new DOMResult();
-				abstractExpandTransformer.transform(new DOMSource(dsdlXslResult.getNode()), abstractExpandResult);
-				
-				Source svrlXslSource = new StreamSource(Checker.class.getResourceAsStream("iso_svrl_for_xslt2.xsl"));
-				Transformer svrlTransformer = transformerFactory.newTransformer(svrlXslSource);
-				
-				DOMResult schematronXsltResult = new DOMResult();
-				svrlTransformer.transform(new DOMSource(abstractExpandResult.getNode()), schematronXsltResult);
-
-				Transformer schematronTransformer = transformerFactory.newTransformer(new DOMSource(schematronXsltResult.getNode()));
-				Source cityGmlSource = new StreamSource(in);
-				
-				SvrlContentHandler handler = new SvrlContentHandler();
-				Result finalResult = new SAXResult(handler);
-				
-				schematronTransformer.transform(cityGmlSource, finalResult);
-				return handler;
-			} catch (TransformerException e) {
-				logger.catching(e);
-			}
-		}
-		return null;
-	}
-
-	private void buildFilters() {
-		FilterConfiguration filterConfig = config.getFilter();
-		if (filterConfig == null) {
-			includeFilters = Collections.emptyList();
-			excludeFilters = Collections.emptyList();
-			return;
-		}
-		excludeFilters = buildExcludeFilters(filterConfig);
-		includeFilters = buildIncludeFilters(filterConfig);
-	}
-
-	private List<Filter> buildExcludeFilters(FilterConfiguration filterConfig) {
-		if (filterConfig == null) {
-			return Collections.emptyList();
-		}
-		ExcludeFilterConfiguration excludeConfig = filterConfig.getExclude();
-		if (excludeConfig == null) {
-			return Collections.emptyList();
-		} else {
-			List<Filter> filters = new ArrayList<>();
-			if (excludeConfig.getTypes() != null) {
-				for (FeatureType excludeType : excludeConfig.getTypes()) {
-					filters.add(new TypeFilter(excludeType));
-				}
-			}
-			if (excludeConfig.getIds() != null) {
-				for (String excludePattern : excludeConfig.getIds()) {
-					Filter f = new EqualsIgnoreCaseFilter(excludePattern);
-					filters.add(f);
-				}
-			}
-			return filters;
-		}
-	}
-
-	private List<Filter> buildIncludeFilters(FilterConfiguration filterConfig) {
-		if (filterConfig == null) {
-			return Collections.emptyList();
-		}
-		IncludeFilterConfiguration includeConfig = filterConfig.getInclude();
-		if (includeConfig == null) {
-			return Collections.emptyList();
-		} else {
-			List<Filter> filters = new ArrayList<>();
-			if (includeConfig.getTypes() != null) {
-				for (FeatureType includeType : includeConfig.getTypes()) {
-					filters.add(new TypeFilter(includeType));
-				}
-			}
-			if (includeConfig.getIds() != null) {
-				for (String includePattern : includeConfig.getIds()) {
-					Filter f = new EqualsIgnoreCaseFilter(includePattern);
-					filters.add(f);
-				}
-			}
-			return filters;
-		}
-	}
-
-	private void setValidationConfig(ValidationConfiguration config) {
-		if (config == null) {
-			throw new IllegalArgumentException("Validation configuration may not be null");
-		}
-		this.config = config;
-		buildFilters();
-		ParserConfiguration parserConfig = config.getParserConfiguration();
-		List<Check> checks = collectEnabledChecksAndInit(parserConfig, config);
-		execLayers = buildExecutionLayers(checks);
-	}
-
-	private List<Check> collectEnabledChecksAndInit(ParserConfiguration parserConfig, ValidationConfiguration config) {
-		Set<CheckId> enabledCheck = new HashSet<>();
-		Map<CheckId, Map<String, String>> parameterMap = new HashMap<>();
-		for (Entry<String, RequirementConfiguration> e : config.getRequirements().entrySet()) {
-			de.hft.stuttgart.citydoctor2.check.Requirement req = Checks.getAvailableRequirements().get(e.getKey());
-			if (req == null) {
-				logger.warn("Could not find any check that satisfies requirement {}, it will not be checked",
-						e.getKey());
-			} else {
-				if (e.getValue().isEnabled()) {
-					// this requirement is enabled
-					insertGlobalParameters(config, enabledCheck, parameterMap, e, req);
-				}
-			}
-		}
-		fillParameterMapsWithDefaultParameter(enabledCheck, parameterMap);
-		ArrayList<Check> checkList = new ArrayList<>();
-		for (CheckId id : enabledCheck) {
-			Check c = checkConfig.getCheckForId(id);
-			c.init(parameterMap.get(id), parserConfig);
-			checkList.add(c);
-		}
-		return checkList;
-	}
-
-	private void insertGlobalParameters(ValidationConfiguration config, Set<CheckId> enabledCheck,
-			Map<CheckId, Map<String, String>> parameterMap, Entry<String, RequirementConfiguration> e,
-			de.hft.stuttgart.citydoctor2.check.Requirement req) {
-		for (CheckPrototype proto : Checks.getCheckPrototypes()) {
-			if (proto.checksRequirements().contains(req)) {
-				// this requirement is checked by this check
-				// put all requirement parameter in the map
-				parameterMap.compute(proto.getCheckId(), (k, v) -> {
-					if (v == null) {
-						v = new HashMap<>();
-						v.put(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, config.getNumberOfRoundingPlacesAsString());
-						v.put(GlobalParameters.MIN_VERTEX_DISTANCE, config.getMinVertexDistanceAsString());
-					}
-					v.putAll(e.getValue().getParameters());
-					return v;
-				});
-				enabledCheck.add(proto.getCheckId());
-				collectDependencyChecks(proto, enabledCheck);
-			}
-		}
-	}
-
-	private void fillParameterMapsWithDefaultParameter(Set<CheckId> enabledCheck,
-			Map<CheckId, Map<String, String>> parameterMap) {
-		for (CheckId id : enabledCheck) {
-			CheckPrototype proto = Checks.getCheckPrototypeForId(id);
-			Map<String, String> map = parameterMap.computeIfAbsent(id, k -> new HashMap<>());
-			for (de.hft.stuttgart.citydoctor2.check.Requirement req : proto.checksRequirements()) {
-				if (proto.checksRequirements().contains(req)) {
-					for (DefaultParameter param : req.getDefaultParameter()) {
-						map.computeIfAbsent(param.getName(), k -> param.getValue());
-					}
-				}
-			}
-		}
-	}
-
-	private void collectDependencyChecks(CheckPrototype proto, Set<CheckId> enabledChecks) {
-		enabledChecks.addAll(proto.getDependencies());
-		for (CheckId id : proto.getDependencies()) {
-			if (enabledChecks.contains(id)) {
-				continue;
-			}
-			CheckPrototype depProto = Checks.getCheckPrototypeForId(id);
-			collectDependencyChecks(depProto, enabledChecks);
-		}
-	}
-
-	private void checkCityModel(CityDoctorModel model, ProgressListener l) {
-		Stream<CityObject> features = model.createFeatureStream();
-		float featureSum = model.getNumberOfFeatures();
-		// stupid lamda with final variable restrictions
-		int[] currentFeature = new int[1];
-		features.forEach(co -> {
-			if (config.getParserConfiguration().useLowMemoryConsumption()) {
-				// no edges have been created yet, create them
-				co.prepareForChecking();
-			}
-			// check every feature
-			executeChecksForCityObject(co);
-
-			if (config.getParserConfiguration().useLowMemoryConsumption()) {
-				// low memory consumption, remove edges again
-				co.clearMetaInformation();
-			}
-			if (l != null) {
-				currentFeature[0]++;
-				l.updateProgress(currentFeature[0] / featureSum);
-			}
-		});
-	}
-
-	private boolean filterObject(CityObject co) {
-		return isObjectIncluded(co, includeFilters, excludeFilters);
-	}
-
-	private boolean isObjectIncluded(CityObject co, List<Filter> includeFilters, List<Filter> excludeFilters) {
-		if (!includeFilters.isEmpty()) {
-			boolean include = false;
-			for (Filter f : includeFilters) {
-				if (f.matches(co)) {
-					include = true;
-					break;
-				}
-			}
-			if (!include) {
-				// not included, ignore
-				return false;
-			}
-		}
-		// check if object is excluded
-		for (Filter f : excludeFilters) {
-			if (f.matches(co)) {
-				// exclude object
-				return false;
-			}
-		}
-		return true;
-	}
-
-	/**
-	 * Checks the city object if it has not been removed by the filters. The check
-	 * result are stored into the city object itself.
-	 * 
-	 * @param co the city object that is going to be checked
-	 */
-	private void executeChecksForCityObject(CityObject co) {
-		if (!filterObject(co)) {
-			return;
-		}
-		executeChecksForCheckable(co);
-	}
-
-	/**
-	 * Executes all checks for the checkable. This will bypass the filters. This
-	 * will clear the old check results
-	 * 
-	 * @param co the checkable.
-	 */
-	public void executeChecksForCheckable(Checkable co) {
-		// throw away old results
-		co.clearAllContainedCheckResults();
-		if (logger.isDebugEnabled()) {
-			logger.debug(Localization.getText("Checker.checkFeature"), co);
-		}
+    }
+
+    private RequirementId mapToRequirement(String requirementName) {
+        try {
+            return RequirementId.valueOf(requirementName);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    public ValidationConfiguration getConfig() {
+        return config;
+    }
+
+    public static SvrlContentHandler executeSchematronValidationIfAvailable(ValidationConfiguration config, File file) {
+        if (file == null || !file.exists()) {
+            return null;
+        }
+        try {
+            return executeSchematronValidationIfAvailable(config, new FileInputStream(file));
+        } catch (FileNotFoundException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    public static SvrlContentHandler executeSchematronValidationIfAvailable(ValidationConfiguration config,
+                                                                            InputStream in) {
+        if (config.getSchematronFilePath() != null && !config.getSchematronFilePath().isEmpty()) {
+            if (logger.isInfoEnabled()) {
+                logger.info(Localization.getText("Checker.schematronValidation"));
+            }
+
+            try {
+                TransformerFactory transformerFactory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", Checker.class.getClassLoader());
+                transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+                transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
+                transformerFactory.setURIResolver((href, base) -> new StreamSource(Checker.class.getResourceAsStream(href)));
+
+                Source dsdlXslSource = new StreamSource(Checker.class.getResourceAsStream("iso_dsdl_include.xsl"));
+                Transformer dsdlXslTransformer = transformerFactory.newTransformer(dsdlXslSource);
+
+                DOMResult dsdlXslResult = new DOMResult();
+                dsdlXslTransformer.transform(new StreamSource(new File(config.getSchematronFilePath())), dsdlXslResult);
+
+                Source abstractExpandXsl = new StreamSource(Checker.class.getResourceAsStream("iso_abstract_expand.xsl"));
+                Transformer abstractExpandTransformer = transformerFactory.newTransformer(abstractExpandXsl);
+
+                DOMResult abstractExpandResult = new DOMResult();
+                abstractExpandTransformer.transform(new DOMSource(dsdlXslResult.getNode()), abstractExpandResult);
+
+                Source svrlXslSource = new StreamSource(Checker.class.getResourceAsStream("iso_svrl_for_xslt2.xsl"));
+                Transformer svrlTransformer = transformerFactory.newTransformer(svrlXslSource);
+
+                DOMResult schematronXsltResult = new DOMResult();
+                svrlTransformer.transform(new DOMSource(abstractExpandResult.getNode()), schematronXsltResult);
+
+                Transformer schematronTransformer = transformerFactory.newTransformer(new DOMSource(schematronXsltResult.getNode()));
+                Source cityGmlSource = new StreamSource(in);
+
+                SvrlContentHandler handler = new SvrlContentHandler();
+                Result finalResult = new SAXResult(handler);
+
+                schematronTransformer.transform(cityGmlSource, finalResult);
+                return handler;
+            } catch (TransformerException e) {
+                logger.catching(e);
+            }
+        }
+        return null;
+    }
+
+    private void buildFilters() {
+        FilterConfiguration filterConfig = config.getFilter();
+        if (filterConfig == null) {
+            includeFilters = Collections.emptyList();
+            excludeFilters = Collections.emptyList();
+            return;
+        }
+        excludeFilters = buildExcludeFilters(filterConfig);
+        includeFilters = buildIncludeFilters(filterConfig);
+    }
+
+    private List<Filter> buildExcludeFilters(FilterConfiguration filterConfig) {
+        if (filterConfig == null) {
+            return Collections.emptyList();
+        }
+        ExcludeFilterConfiguration excludeConfig = filterConfig.getExclude();
+        if (excludeConfig == null) {
+            return Collections.emptyList();
+        } else {
+            List<Filter> filters = new ArrayList<>();
+            if (excludeConfig.getTypes() != null) {
+                for (FeatureType excludeType : excludeConfig.getTypes()) {
+                    filters.add(new TypeFilter(excludeType));
+                }
+            }
+            if (excludeConfig.getIds() != null) {
+                for (String excludePattern : excludeConfig.getIds()) {
+                    Filter f = new EqualsIgnoreCaseFilter(excludePattern);
+                    filters.add(f);
+                }
+            }
+            return filters;
+        }
+    }
+
+    private List<Filter> buildIncludeFilters(FilterConfiguration filterConfig) {
+        if (filterConfig == null) {
+            return Collections.emptyList();
+        }
+        IncludeFilterConfiguration includeConfig = filterConfig.getInclude();
+        if (includeConfig == null) {
+            return Collections.emptyList();
+        } else {
+            List<Filter> filters = new ArrayList<>();
+            if (includeConfig.getTypes() != null) {
+                for (FeatureType includeType : includeConfig.getTypes()) {
+                    filters.add(new TypeFilter(includeType));
+                }
+            }
+            if (includeConfig.getIds() != null) {
+                for (String includePattern : includeConfig.getIds()) {
+                    Filter f = new EqualsIgnoreCaseFilter(includePattern);
+                    filters.add(f);
+                }
+            }
+            return filters;
+        }
+    }
+
+    private void setValidationConfig(ValidationConfiguration config) {
+        if (config == null) {
+            throw new IllegalArgumentException("Validation configuration may not be null");
+        }
+        this.config = config;
+        buildFilters();
+        ParserConfiguration parserConfig = config.getParserConfiguration();
+        List<Check> checks = collectEnabledChecksAndInit(parserConfig, config);
+        execLayers = buildExecutionLayers(checks);
+    }
+
+    private List<Check> collectEnabledChecksAndInit(ParserConfiguration parserConfig, ValidationConfiguration config) {
+        Set<CheckId> enabledCheck = new HashSet<>();
+        Map<CheckId, Map<String, String>> parameterMap = new HashMap<>();
+        for (Entry<String, RequirementConfiguration> e : config.getRequirements().entrySet()) {
+            de.hft.stuttgart.citydoctor2.check.Requirement req = Checks.getAvailableRequirements().get(e.getKey());
+            if (req == null) {
+                logger.warn("Could not find any check that satisfies requirement {}, it will not be checked",
+                        e.getKey());
+            } else {
+                if (e.getValue().isEnabled()) {
+                    // this requirement is enabled
+                    insertGlobalParameters(config, enabledCheck, parameterMap, e, req);
+                }
+            }
+        }
+        fillParameterMapsWithDefaultParameter(enabledCheck, parameterMap);
+        ArrayList<Check> checkList = new ArrayList<>();
+        for (CheckId id : enabledCheck) {
+            Check c = checkConfig.getCheckForId(id);
+            c.init(parameterMap.get(id), parserConfig);
+            checkList.add(c);
+        }
+        return checkList;
+    }
+
+    private void insertGlobalParameters(ValidationConfiguration config, Set<CheckId> enabledCheck,
+                                        Map<CheckId, Map<String, String>> parameterMap, Entry<String, RequirementConfiguration> e,
+                                        de.hft.stuttgart.citydoctor2.check.Requirement req) {
+        for (CheckPrototype proto : Checks.getCheckPrototypes()) {
+            if (proto.checksRequirements().contains(req)) {
+                // this requirement is checked by this check
+                // put all requirement parameter in the map
+                parameterMap.compute(proto.getCheckId(), (k, v) -> {
+                    if (v == null) {
+                        v = new HashMap<>();
+                        v.put(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, config.getNumberOfRoundingPlacesAsString());
+                        v.put(GlobalParameters.MIN_VERTEX_DISTANCE, config.getMinVertexDistanceAsString());
+                    }
+                    v.putAll(e.getValue().getParameters());
+                    return v;
+                });
+                enabledCheck.add(proto.getCheckId());
+                collectDependencyChecks(proto, enabledCheck);
+            }
+        }
+    }
+
+    private void fillParameterMapsWithDefaultParameter(Set<CheckId> enabledCheck,
+                                                       Map<CheckId, Map<String, String>> parameterMap) {
+        for (CheckId id : enabledCheck) {
+            CheckPrototype proto = Checks.getCheckPrototypeForId(id);
+            Map<String, String> map = parameterMap.computeIfAbsent(id, k -> new HashMap<>());
+            for (de.hft.stuttgart.citydoctor2.check.Requirement req : proto.checksRequirements()) {
+                if (proto.checksRequirements().contains(req)) {
+                    for (DefaultParameter param : req.getDefaultParameter()) {
+                        map.computeIfAbsent(param.getName(), k -> param.getValue());
+                    }
+                }
+            }
+        }
+    }
+
+    private void collectDependencyChecks(CheckPrototype proto, Set<CheckId> enabledChecks) {
+        enabledChecks.addAll(proto.getDependencies());
+        for (CheckId id : proto.getDependencies()) {
+            if (enabledChecks.contains(id)) {
+                continue;
+            }
+            CheckPrototype depProto = Checks.getCheckPrototypeForId(id);
+            collectDependencyChecks(depProto, enabledChecks);
+        }
+    }
+
+    private void checkCityModel(CityDoctorModel model, ProgressListener l) {
+        Stream<CityObject> features = model.createFeatureStream();
+        float featureSum = model.getNumberOfFeatures();
+        // stupid lamda with final variable restrictions
+        int[] currentFeature = new int[1];
+        features.forEach(co -> {
+            if (config.getParserConfiguration().useLowMemoryConsumption()) {
+                // no edges have been created yet, create them
+                co.prepareForChecking();
+            }
+            // check every feature
+            executeChecksForCityObject(co);
+
+            if (config.getParserConfiguration().useLowMemoryConsumption()) {
+                // low memory consumption, remove edges again
+                co.clearMetaInformation();
+            }
+            if (l != null) {
+                currentFeature[0]++;
+                l.updateProgress(currentFeature[0] / featureSum);
+            }
+        });
+    }
+
+    private boolean filterObject(CityObject co) {
+        return isObjectIncluded(co, includeFilters, excludeFilters);
+    }
+
+    private boolean isObjectIncluded(CityObject co, List<Filter> includeFilters, List<Filter> excludeFilters) {
+        if (!includeFilters.isEmpty()) {
+            boolean include = false;
+            for (Filter f : includeFilters) {
+                if (f.matches(co)) {
+                    include = true;
+                    break;
+                }
+            }
+            if (!include) {
+                // not included, ignore
+                return false;
+            }
+        }
+        // check if object is excluded
+        for (Filter f : excludeFilters) {
+            if (f.matches(co)) {
+                // exclude object
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks the city object if it has not been removed by the filters. The check
+     * result are stored into the city object itself.
+     *
+     * @param co the city object that is going to be checked
+     */
+    private void executeChecksForCityObject(CityObject co) {
+        if (!filterObject(co)) {
+            return;
+        }
+        executeChecksForCheckable(co);
+    }
+
+    /**
+     * Executes all checks for the checkable. This will bypass the filters. This
+     * will clear the old check results
+     *
+     * @param co the checkable.
+     */
+    public void executeChecksForCheckable(Checkable co) {
+        // throw away old results
+        co.clearAllContainedCheckResults();
+        if (logger.isDebugEnabled()) {
+            logger.debug(Localization.getText("Checker.checkFeature"), co);
+        }
         for (List<Check> execLayer : execLayers) {
             for (Check check : execLayer) {
                 if (logger.isTraceEnabled()) {
@@ -700,162 +697,162 @@ public class Checker {
                 co.accept(check);
             }
         }
-	}
-
-	public static List<List<Check>> buildExecutionLayers(List<Check> checks) {
-		List<List<Check>> result = new ArrayList<>();
-
-		Set<Check> availableChecks = new HashSet<>(checks);
-		Set<CheckId> usedChecks = new HashSet<>();
-
-		while (!availableChecks.isEmpty()) {
-			List<Check> layer = new ArrayList<>();
-			Iterator<Check> iterator = availableChecks.iterator();
-			while (iterator.hasNext()) {
-				Check c = iterator.next();
-				boolean hasUnusedDependency = searchForUnusedDependency(usedChecks, c);
-				if (!hasUnusedDependency) {
-					iterator.remove();
-					layer.add(new CheckContainer(c));
-				}
-			}
-			if (layer.isEmpty()) {
-				throw new IllegalStateException(
-						"There are checks that have dependencies that are not executed or are unknown, aborting");
-			}
-			result.add(layer);
-			for (Check c : layer) {
-				usedChecks.add(c.getCheckId());
-			}
-		}
-		return result;
-	}
-
-	private static boolean searchForUnusedDependency(Set<CheckId> usedChecks, Check c) {
-		boolean hasUnusedDependency = false;
-		for (CheckId id : c.getDependencies()) {
-			if (!usedChecks.contains(id)) {
-				hasUnusedDependency = true;
-				break;
-			}
-		}
-		return hasUnusedDependency;
-	}
-
-	public static void streamCheck (CityGmlZipEntry entry, String xmlOutput, String pdfOutput, ValidationConfiguration config,
-									String outputFile) throws IOException, CityGmlParseException{
-		try (BufferedOutputStream xmlBos = getXmlOutputMaybe(xmlOutput);
-			 BufferedOutputStream pdfBos = getPdfOutputMaybe(pdfOutput)) {
-			Checker c = new Checker(config, null);
-			String fileName = entry.getFileName();
-
-			// create reporter if available
-			XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName);
-			PdfStreamReporter pdfReporter = getPdfReporter(config, pdfBos, fileName);
-
-			// execute schematron first
-			try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
-				SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, entryFile.getInputStream());
-
-				CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, null);
-				// parse and validate
-				CityGmlParser.streamCityGml(entry, config.getParserConfiguration(), con, outputFile);
-
-				// write reports if available
-				writeReport(xmlReporter);
-				writeReport(pdfReporter);
-			}
-		} catch (CheckReportWriteException e) {
-			logger.error(Localization.getText("Checker.failReports"), e);
-		}
-	}
-
-
-	public static void streamCheck(File inputFile, String xmlOutput, String pdfOutput, ValidationConfiguration config,
-			String outputFile) throws IOException, CityGmlParseException {
-		streamCheck(inputFile, xmlOutput, pdfOutput, config, null, outputFile);
-	}
-
-	public static void streamCheck(File inputFile, String xmlOutput, String pdfOutput, ValidationConfiguration config,
-			FeatureCheckedListener l, String outputFile) throws IOException, CityGmlParseException {
-		try (BufferedOutputStream xmlBos = getXmlOutputMaybe(xmlOutput);
-				BufferedOutputStream pdfBos = getPdfOutputMaybe(pdfOutput)) {
-			Checker c = new Checker(config, null);
-			String fileName = inputFile.getName();
-
-			// create reporter if available
-			XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName);
-			PdfStreamReporter pdfReporter = getPdfReporter(config, pdfBos, fileName);
-
-			// execute schematron first
-			SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile);
-			CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, l);
-			// parse and validate
-			CityGmlParser.streamCityGml(inputFile.getAbsolutePath(), config.getParserConfiguration(), con, outputFile);
-
-			// write reports if available
-			writeReport(xmlReporter);
-			writeReport(pdfReporter);
-		} catch (CheckReportWriteException e) {
-			logger.error(Localization.getText("Checker.failReports"), e);
-		}
-	}
-
-	private static XmlStreamReporter getXmlReporter(ValidationConfiguration config, BufferedOutputStream xmlBos,
-			String fileName) {
-		XmlStreamReporter xmlReporter;
-		if (xmlBos != null) {
-			xmlReporter = new XmlStreamReporter(xmlBos, fileName, config);
-		} else {
-			xmlReporter = null;
-		}
-		return xmlReporter;
-	}
-
-	private static PdfStreamReporter getPdfReporter(ValidationConfiguration config, BufferedOutputStream pdfBos,
-			String fileName) {
-		PdfStreamReporter pdfReporter;
-		if (pdfBos != null) {
-			pdfReporter = new PdfStreamReporter(pdfBos, fileName, config);
-		} else {
-			pdfReporter = null;
-		}
-		return pdfReporter;
-	}
-
-	public static void writeReport(StreamReporter reporter) throws CheckReportWriteException {
-		if (reporter != null) {
-			reporter.finishReport();
-		}
-	}
-
-	public static BufferedOutputStream getPdfOutputMaybe(String pdfOutput) throws FileNotFoundException {
-		return pdfOutput != null ? new BufferedOutputStream(new FileOutputStream(pdfOutput)) : null;
-	}
-
-	public static BufferedOutputStream getXmlOutputMaybe(String xmlOutput) throws FileNotFoundException {
-		return xmlOutput != null ? new BufferedOutputStream(new FileOutputStream(xmlOutput)) : null;
-	}
-
-	/**
-	 * Checks the city object and writes report information into reporters. Clears
-	 * old check results. If the city object would be filtered by the configured
-	 * filters it is ignored and old check results are not cleared.
-	 * 
-	 * @param xmlReporter a xml reporter
-	 * @param pdfReporter a pdf reporter
-	 * @param co          the city object to be checked
-	 */
-	public void checkFeature(XmlStreamReporter xmlReporter, PdfStreamReporter pdfReporter, CityObject co) {
-		if (logger.isDebugEnabled()) {
-			logger.debug(Localization.getText("Checker.checkFeature"), co);
-		}
-		executeChecksForCityObject(co);
-		if (xmlReporter != null) {
-			xmlReporter.report(co);
-		}
-		if (pdfReporter != null) {
-			pdfReporter.report(co);
-		}
-	}
+    }
+
+    public static List<List<Check>> buildExecutionLayers(List<Check> checks) {
+        List<List<Check>> result = new ArrayList<>();
+
+        Set<Check> availableChecks = new HashSet<>(checks);
+        Set<CheckId> usedChecks = new HashSet<>();
+
+        while (!availableChecks.isEmpty()) {
+            List<Check> layer = new ArrayList<>();
+            Iterator<Check> iterator = availableChecks.iterator();
+            while (iterator.hasNext()) {
+                Check c = iterator.next();
+                boolean hasUnusedDependency = searchForUnusedDependency(usedChecks, c);
+                if (!hasUnusedDependency) {
+                    iterator.remove();
+                    layer.add(new CheckContainer(c));
+                }
+            }
+            if (layer.isEmpty()) {
+                throw new IllegalStateException(
+                        "There are checks that have dependencies that are not executed or are unknown, aborting");
+            }
+            result.add(layer);
+            for (Check c : layer) {
+                usedChecks.add(c.getCheckId());
+            }
+        }
+        return result;
+    }
+
+    private static boolean searchForUnusedDependency(Set<CheckId> usedChecks, Check c) {
+        boolean hasUnusedDependency = false;
+        for (CheckId id : c.getDependencies()) {
+            if (!usedChecks.contains(id)) {
+                hasUnusedDependency = true;
+                break;
+            }
+        }
+        return hasUnusedDependency;
+    }
+
+    public static void streamCheck(CityGmlZipEntry entry, String xmlOutput, String pdfOutput, ValidationConfiguration config,
+                                   String outputFile) throws IOException, CityGmlParseException {
+        try (BufferedOutputStream xmlBos = getXmlOutputMaybe(xmlOutput);
+             BufferedOutputStream pdfBos = getPdfOutputMaybe(pdfOutput)) {
+            Checker c = new Checker(config, null);
+            String fileName = entry.getFileName();
+
+            // create reporter if available
+            XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName);
+            PdfStreamReporter pdfReporter = getPdfReporter(config, pdfBos, fileName);
+
+            // execute schematron first
+            try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
+                SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, entryFile.getInputStream());
+
+                CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, null);
+                // parse and validate
+                CityGmlParser.streamCityGml(entry, config.getParserConfiguration(), con, outputFile);
+
+                // write reports if available
+                writeReport(xmlReporter);
+                writeReport(pdfReporter);
+            }
+        } catch (CheckReportWriteException e) {
+            logger.error(Localization.getText("Checker.failReports"), e);
+        }
+    }
+
+
+    public static void streamCheck(File inputFile, String xmlOutput, String pdfOutput, ValidationConfiguration config,
+                                   String outputFile) throws IOException, CityGmlParseException {
+        streamCheck(inputFile, xmlOutput, pdfOutput, config, null, outputFile);
+    }
+
+    public static void streamCheck(File inputFile, String xmlOutput, String pdfOutput, ValidationConfiguration config,
+                                   FeatureCheckedListener l, String outputFile) throws IOException, CityGmlParseException {
+        try (BufferedOutputStream xmlBos = getXmlOutputMaybe(xmlOutput);
+             BufferedOutputStream pdfBos = getPdfOutputMaybe(pdfOutput)) {
+            Checker c = new Checker(config, null);
+            String fileName = inputFile.getName();
+
+            // create reporter if available
+            XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName);
+            PdfStreamReporter pdfReporter = getPdfReporter(config, pdfBos, fileName);
+
+            // execute schematron first
+            SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile);
+            CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, l);
+            // parse and validate
+            CityGmlParser.streamCityGml(inputFile.getAbsolutePath(), config.getParserConfiguration(), con, outputFile);
+
+            // write reports if available
+            writeReport(xmlReporter);
+            writeReport(pdfReporter);
+        } catch (CheckReportWriteException e) {
+            logger.error(Localization.getText("Checker.failReports"), e);
+        }
+    }
+
+    private static XmlStreamReporter getXmlReporter(ValidationConfiguration config, BufferedOutputStream xmlBos,
+                                                    String fileName) {
+        XmlStreamReporter xmlReporter;
+        if (xmlBos != null) {
+            xmlReporter = new XmlStreamReporter(xmlBos, fileName, config);
+        } else {
+            xmlReporter = null;
+        }
+        return xmlReporter;
+    }
+
+    private static PdfStreamReporter getPdfReporter(ValidationConfiguration config, BufferedOutputStream pdfBos,
+                                                    String fileName) {
+        PdfStreamReporter pdfReporter;
+        if (pdfBos != null) {
+            pdfReporter = new PdfStreamReporter(pdfBos, fileName, config);
+        } else {
+            pdfReporter = null;
+        }
+        return pdfReporter;
+    }
+
+    public static void writeReport(StreamReporter reporter) throws CheckReportWriteException {
+        if (reporter != null) {
+            reporter.finishReport();
+        }
+    }
+
+    public static BufferedOutputStream getPdfOutputMaybe(String pdfOutput) throws FileNotFoundException {
+        return pdfOutput != null ? new BufferedOutputStream(new FileOutputStream(pdfOutput)) : null;
+    }
+
+    public static BufferedOutputStream getXmlOutputMaybe(String xmlOutput) throws FileNotFoundException {
+        return xmlOutput != null ? new BufferedOutputStream(new FileOutputStream(xmlOutput)) : null;
+    }
+
+    /**
+     * Checks the city object and writes report information into reporters. Clears
+     * old check results. If the city object would be filtered by the configured
+     * filters it is ignored and old check results are not cleared.
+     *
+     * @param xmlReporter a xml reporter
+     * @param pdfReporter a pdf reporter
+     * @param co          the city object to be checked
+     */
+    public void checkFeature(XmlStreamReporter xmlReporter, PdfStreamReporter pdfReporter, CityObject co) {
+        if (logger.isDebugEnabled()) {
+            logger.debug(Localization.getText("Checker.checkFeature"), co);
+        }
+        executeChecksForCityObject(co);
+        if (xmlReporter != null) {
+            xmlReporter.report(co);
+        }
+        if (pdfReporter != null) {
+            pdfReporter.report(co);
+        }
+    }
 }
diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java
index 8e2df6a..7b1a04d 100644
--- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java
+++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java
@@ -1,6 +1,6 @@
 /*-
  *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
- * 
+ *
  *  This file is part of CityDoctor2.
  *
  *  CityDoctor2 is free software: you can redistribute it and/or modify
@@ -18,16 +18,6 @@
  */
 package de.hft.stuttgart.citydoctor2.check;
 
-import java.io.File;
-import java.io.IOException;
-
-import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
-import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive;
-import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
 import de.hft.stuttgart.citydoctor2.CityDoctorValidation;
 import de.hft.stuttgart.citydoctor2.datastructure.Building;
 import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
@@ -35,99 +25,106 @@ import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
 import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
 import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
 import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
+import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
+import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive;
+import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 /**
- * 
  * @author Matthias Betz
- *
  */
 public class CheckerTest {
 
-	@Rule
-	public TemporaryFolder folder = new TemporaryFolder();
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
 
-	@Test
-	public void testSchematron() throws CityGmlParseException, InvalidGmlFileException {
-		ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
-		config.getRequirements().get(Requirement.R_SE_BS_ROOF_UNFRAGMENTED.toString()).setEnabled(false);
-		config.setSchematronFilePathInGlobalParameters("src/test/resources/schematronTest.xml");
-		CityDoctorModel model = CityGmlParser.parseCityGmlFile(
-				"src/test/resources/SimpleSolid_SrefBS_SchematronTest.gml", config.getParserConfiguration());
-		Checker checker = new Checker(config, model);
-		checker.runChecks();
-		for (Building b : model.getBuildings()) {
-			if (b.getGmlId().getGmlString().equals("_Simple_BD.1")) {
-				assertTrue(b.containsAnyError());
-			} else {
-				assertFalse(b.containsAnyError());
-			}
-		}
-		assertFalse(model.getGlobalErrors().isEmpty());
-	}
+    @Test
+    public void testSchematron() throws CityGmlParseException, InvalidGmlFileException {
+        ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
+        config.getRequirements().get(Requirement.R_SE_BS_ROOF_UNFRAGMENTED.toString()).setEnabled(false);
+        config.setSchematronFilePathInGlobalParameters("src/test/resources/schematronTest.xml");
+        CityDoctorModel model = CityGmlParser.parseCityGmlFile(
+                "src/test/resources/SimpleSolid_SrefBS_SchematronTest.gml", config.getParserConfiguration());
+        Checker checker = new Checker(config, model);
+        checker.runChecks();
+        for (Building b : model.getBuildings()) {
+            if (b.getGmlId().getGmlString().equals("_Simple_BD.1")) {
+                assertTrue(b.containsAnyError());
+            } else {
+                assertFalse(b.containsAnyError());
+            }
+        }
+        assertFalse(model.getGlobalErrors().isEmpty());
+    }
 
-	@Test
-	public void testChecker() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
+    @Test
+    public void testChecker() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
 
-		File f = folder.newFile();
-		File f2 = folder.newFile();
-		try {
-			String[] args = new String[6];
-			args[0] = "-in";
-			args[1] = "src/test/resources/QA-CS-CONCOMP.gml";
-			args[2] = "-xmlReport";
-			args[3] = f.getAbsolutePath();
-			args[4] = "-pdfReport";
-			args[5] = f2.getAbsolutePath();
-			CityDoctorValidation.main(args);
-			assertTrue(f.exists());
-			assertTrue(f2.exists());
-		} finally {
-			f.delete();
-			f2.delete();
-		}
-	}
+        File f = folder.newFile();
+        File f2 = folder.newFile();
+        try {
+            String[] args = new String[6];
+            args[0] = "-in";
+            args[1] = "src/test/resources/QA-CS-CONCOMP.gml";
+            args[2] = "-xmlReport";
+            args[3] = f.getAbsolutePath();
+            args[4] = "-pdfReport";
+            args[5] = f2.getAbsolutePath();
+            CityDoctorValidation.main(args);
+            assertTrue(f.exists());
+            assertTrue(f2.exists());
+        } finally {
+            f.delete();
+            f2.delete();
+        }
+    }
 
-	@Test
-	public void testStreaming() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
-		File f = folder.newFile();
-		File f2 = folder.newFile();
-		File f3 = folder.newFile();
-		try {
-			String[] args = new String[10];
-			args[0] = "-in";
-			args[1] = "src/test/resources/testarea.gml";
-			args[2] = "-config";
-			args[3] = "src/test/resources/testConfigWithStreaming.yml";
-			args[4] = "-pdfReport";
-			args[5] = f.getAbsolutePath();
-			args[6] = "-xmlReport";
-			args[7] = f2.getAbsolutePath();
-			args[8] = "-out";
-			args[9] = f3.getAbsolutePath();
-			CityDoctorValidation.main(args);
-			assertTrue(f.exists());
-			assertTrue(f2.exists());
-			assertTrue(f3.exists());
-		} finally {
-			f.delete();
-			f2.delete();
-			f3.delete();
-		}
-	}
+    @Test
+    public void testStreaming() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
+        File f = folder.newFile();
+        File f2 = folder.newFile();
+        File f3 = folder.newFile();
+        try {
+            String[] args = new String[10];
+            args[0] = "-in";
+            args[1] = "src/test/resources/testarea.gml";
+            args[2] = "-config";
+            args[3] = "src/test/resources/testConfigWithStreaming.yml";
+            args[4] = "-pdfReport";
+            args[5] = f.getAbsolutePath();
+            args[6] = "-xmlReport";
+            args[7] = f2.getAbsolutePath();
+            args[8] = "-out";
+            args[9] = f3.getAbsolutePath();
+            CityDoctorValidation.main(args);
+            assertTrue(f.exists());
+            assertTrue(f2.exists());
+            assertTrue(f3.exists());
+        } finally {
+            f.delete();
+            f2.delete();
+            f3.delete();
+        }
+    }
 
-	@Test
-	public void testZipEntryChecking() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
-		CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zipArchive.zip");
-		assertNotNull(cgmlArch);
-		cgmlArch.mountArchive(new ParserConfiguration(8,false));
-		ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
-		for (CityGmlZipEntry entry : cgmlArch.getEntries()){
-			Checker.streamCheck(entry, null, null, config, null );
-		}
-	}
+    @Test
+    public void testZipEntryChecking() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
+        CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zipArchive.zip");
+        assertNotNull(cgmlArch);
+        cgmlArch.mountArchive(new ParserConfiguration(8, false));
+        ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
+        for (CityGmlZipEntry entry : cgmlArch.getEntries()) {
+            Checker.streamCheck(entry, null, null, config, null);
+        }
+    }
 
 }
-- 
GitLab