Commit 4b27a7e4 authored by Luna Riegel's avatar Luna Riegel
Browse files

Merge branch 'dev_db_config' into 'dev'

Version 3.18.2

See merge request !39
parents d3ca6500 45d4909d
Pipeline #12347 passed with stage
in 2 minutes and 5 seconds
package de.hft.stuttgart.citydoctor2.exceptions;
import java.io.Serial;
public class CityObjectCacheException extends RuntimeException{
@Serial
private static final long serialVersionUID = -460467145629964615L;
public CityObjectCacheException(String message) {
super(message);
}
public CityObjectCacheException(String message, Throwable cause) {
super(message, cause);
}
}
package de.hft.stuttgart.citydoctor2.exceptions;
import java.io.Serial;
public class EmbeddedDatabaseHandlerException extends RuntimeException{
@Serial
private static final long serialVersionUID = -7848325704234347425L;
public EmbeddedDatabaseHandlerException(String message) {
super(message);
}
public EmbeddedDatabaseHandlerException(String message, Throwable cause) {
super(message, cause);
}
public EmbeddedDatabaseHandlerException(Throwable cause){
super(cause);
}
}
...@@ -28,6 +28,7 @@ import java.util.function.Function; ...@@ -28,6 +28,7 @@ import java.util.function.Function;
import de.hft.stuttgart.citydoctor2.database.FeatureCache; import de.hft.stuttgart.citydoctor2.database.FeatureCache;
import de.hft.stuttgart.citydoctor2.database.UnconnectedCache; import de.hft.stuttgart.citydoctor2.database.UnconnectedCache;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
import de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject; import de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -168,7 +169,7 @@ public class Citygml3FeatureMapper extends ObjectWalker { ...@@ -168,7 +169,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private static final Logger logger = LogManager.getLogger(Citygml3FeatureMapper.class); private static final Logger logger = LogManager.getLogger(Citygml3FeatureMapper.class);
private static FeatureCache featureCache = new FeatureCache(); private static final FeatureCache featureCache = new FeatureCache();
private final CityDoctorModel model; private final CityDoctorModel model;
private final ParserConfiguration config; private final ParserConfiguration config;
private final Path directory; private final Path directory;
...@@ -207,6 +208,7 @@ public class Citygml3FeatureMapper extends ObjectWalker { ...@@ -207,6 +208,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
return; return;
} }
boolean xLinkGlobalError = false; boolean xLinkGlobalError = false;
String emptyXLinkLog = Localization.getText("CityGmlFeatureMapper.emptyCrossFeatureReference");
List<String> crossRefs = new ArrayList<>(); List<String> crossRefs = new ArrayList<>();
for (Map.Entry<String, List<GmlId>> entry : unresolvedPolyRefIDMap.entrySet()) { for (Map.Entry<String, List<GmlId>> entry : unresolvedPolyRefIDMap.entrySet()) {
String id = entry.getKey(); String id = entry.getKey();
...@@ -217,18 +219,16 @@ public class Citygml3FeatureMapper extends ObjectWalker { ...@@ -217,18 +219,16 @@ public class Citygml3FeatureMapper extends ObjectWalker {
StringJoiner joiner = new StringJoiner(", "); StringJoiner joiner = new StringJoiner(", ");
gmlIds.forEach(gmlId -> joiner.add(gmlId.toString())); gmlIds.forEach(gmlId -> joiner.add(gmlId.toString()));
GmlId crossFeatureId = parsedPolygonsIdMap.get(id); GmlId crossFeatureId = parsedPolygonsIdMap.get(id);
//TODO: Localize String logger.warn(emptyXLinkLog, id, crossFeatureId, joiner);
logger.warn("Polygon {} of Feature {} is being referenced in other Features: {}", id, crossFeatureId, joiner);
crossRefs.add(id); crossRefs.add(id);
} }
} }
if (xLinkGlobalError) { if (xLinkGlobalError) {
//TODO: Localize String logger.warn(Localization.getText("CityGmlFeatureMapper.crossFeatureReferencesDetected"));
logger.warn("Model has Features containing cross-feature references without their own copies of the referenced polygons");
} }
crossRefs.forEach(unresolvedPolyRefIDMap::remove); crossRefs.forEach(unresolvedPolyRefIDMap::remove);
if(!unresolvedPolyRefIDMap.isEmpty()) { if(!unresolvedPolyRefIDMap.isEmpty()) {
logger.warn("Model contains polygon references that could not be found"); logger.warn(Localization.getText("CityGmlFeatureMapper.unresolvedReferencesDetected"));
} }
} }
...@@ -941,6 +941,7 @@ public class Citygml3FeatureMapper extends ObjectWalker { ...@@ -941,6 +941,7 @@ public class Citygml3FeatureMapper extends ObjectWalker {
co.clearGmlGeometries(); co.clearGmlGeometries();
resolveAndClearReferences(co); resolveAndClearReferences(co);
updateEdgesAndVertices(co); updateEdgesAndVertices(co);
co.setBbox(BoundingBox.of(co));
} }
private void mapAbstractTransportationSpace(AbstractTransportationSpace ats, TransportationSpace trsp) { private void mapAbstractTransportationSpace(AbstractTransportationSpace ats, TransportationSpace trsp) {
......
...@@ -300,12 +300,6 @@ public class CityGmlParser { ...@@ -300,12 +300,6 @@ public class CityGmlParser {
} }
} }
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, public static void streamCityGml(File file, ParserConfiguration parserConfig, CityGmlConsumer cityObjectConsumer,
String outputFile) throws CityGmlParseException { String outputFile) throws CityGmlParseException {
streamCityGml(file.toPath(), parserConfig, null, cityObjectConsumer, outputFile); streamCityGml(file.toPath(), parserConfig, null, cityObjectConsumer, outputFile);
......
...@@ -6,15 +6,18 @@ CheckContainer.error=Unexpected exception while executing check: {} ...@@ -6,15 +6,18 @@ CheckContainer.error=Unexpected exception while executing check: {}
CheckDialog.availableChecksLabel=Available Checks CheckDialog.availableChecksLabel=Available Checks
CheckDialog.cancelBtn=Cancel CheckDialog.cancelBtn=Cancel
CheckDialog.checkBtn=Check CheckDialog.checkBtn=Check
CheckDialog.checkDescriptionsLabel=Explanations for the requirements are available on CityDoctor's homepage
CheckDialog.checkEnabled=Enabled CheckDialog.checkEnabled=Enabled
CheckDialog.checkName=Name CheckDialog.checkName=Name
CheckDialog.checksDone=Checks done CheckDialog.checksDone=Checks done
CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information. CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information.
CheckDialog.checksTab=Checks CheckDialog.checksTab=Checks
CheckDialog.clickHereToOpen=[Click here to open]
CheckDialog.failedChecks=Failed to execute checks CheckDialog.failedChecks=Failed to execute checks
CheckDialog.filterTab=Filter CheckDialog.filterTab=Filter
CheckDialog.geometricChecksLabel=Geometric Checks CheckDialog.geometricChecksLabel=Geometric Checks
CheckDialog.globalParametersLabel=Global Parameters CheckDialog.globalParametersLabel=Global Parameters
CheckDialog.homepageHyperlink=https://transfer.hft-stuttgart.de/pages/citydoctor/citydoctorhomepage/en/requirements/
CheckDialog.noPathError=Output path is missing! CheckDialog.noPathError=Output path is missing!
CheckDialog.outputPathBtn=Select CheckDialog.outputPathBtn=Select
CheckDialog.outputPathLabel=Output directory (Required): CheckDialog.outputPathLabel=Output directory (Required):
...@@ -25,12 +28,14 @@ CheckDialog.schematronChooserTitle=Choose schematron file ... ...@@ -25,12 +28,14 @@ CheckDialog.schematronChooserTitle=Choose schematron file ...
CheckDialog.schematronFileLabel=Schematron File: CheckDialog.schematronFileLabel=Schematron File:
CheckDialog.schematronFileNotExisting=Schematron file does not exist, Schematron will be skipped CheckDialog.schematronFileNotExisting=Schematron file does not exist, Schematron will be skipped
CheckDialog.schematronFiles=Schematron Files CheckDialog.schematronFiles=Schematron Files
CheckDialog.selectAllChecksBtn=Select All
CheckDialog.selectBtn=Select CheckDialog.selectBtn=Select
CheckDialog.semanticChecksLabel=Semantic Checks CheckDialog.semanticChecksLabel=Semantic Checks
CheckDialog.startingChecks=Starting checks CheckDialog.startingChecks=Starting checks
CheckDialog.streamCheckLabel=Citymodels are not loaded and kept in memory. Check results are saved to the QualityADE in copies of the input files. CheckDialog.streamCheckLabel=Citymodels are not loaded and kept in memory. Check results are saved to the QualityADE in copies of the input files.
CheckDialog.streamCheckOption=Use low memory mode CheckDialog.streamCheckOption=Use low memory mode
CheckDialog.title=Check Configuration CheckDialog.title=Check Configuration
CheckDialog.unselectAllChecksBtn=Unselect All
CheckDialog.validationConfiguration=Validation Configuration CheckDialog.validationConfiguration=Validation Configuration
CheckDialog.xmlReportsOption=Create XML reports CheckDialog.xmlReportsOption=Create XML reports
Checker.checkFeature=Checking feature: {} Checker.checkFeature=Checking feature: {}
...@@ -70,6 +75,9 @@ CityDoctorValidation.notExactlyOneOutputFile=Specify exactly one file as output. ...@@ -70,6 +75,9 @@ CityDoctorValidation.notExactlyOneOutputFile=Specify exactly one file as output.
CityDoctorValidation.notExactlyOnePDFOutput=Specify exactly one file as pdfReport CityDoctorValidation.notExactlyOnePDFOutput=Specify exactly one file as pdfReport
CityDoctorValidation.notExactlyOneXMLOutput=Specify exactly one file as xmlReport CityDoctorValidation.notExactlyOneXMLOutput=Specify exactly one file as xmlReport
CityDoctorValidation.wrongInputFileFormat=Input file '{}' does not end with .gml or .xml CityDoctorValidation.wrongInputFileFormat=Input file '{}' does not end with .gml or .xml
CityGmlFeatureMapper.crossFeatureReferencesDetected=Model has Features containing cross-feature references without their own copies of the referenced polygons
CityGmlFeatureMapper.emptyCrossFeatureReference=Polygon {} of Feature {} is being referenced in other Features: {}
CityGmlFeatureMapper.unresolvedReferencesDetected=Model contains polygon references that could not be found
CityGmlParser.chunkReadFailed=Failed to read GML file in chunks, falling back to reading the complete file CityGmlParser.chunkReadFailed=Failed to read GML file in chunks, falling back to reading the complete file
CityGmlParser.convertCrsToUtmZoneN=Converting coordinate system to UTM zone {}N CityGmlParser.convertCrsToUtmZoneN=Converting coordinate system to UTM zone {}N
CityGmlParser.convertCrsToUtmZoneS=Converting coordinate system to UTM zone {}S CityGmlParser.convertCrsToUtmZoneS=Converting coordinate system to UTM zone {}S
...@@ -99,6 +107,9 @@ DatabaseHandler.serializationFailure=Serialization of CityObject {} failed! ...@@ -99,6 +107,9 @@ DatabaseHandler.serializationFailure=Serialization of CityObject {} failed!
DatabaseHandler.setupFailure=FATAL ERROR: Creation of embedded database failed! DatabaseHandler.setupFailure=FATAL ERROR: Creation of embedded database failed!
DatabaseHandler.tableFailure=FATAL ERROR: Creation of features table failed! DatabaseHandler.tableFailure=FATAL ERROR: Creation of features table failed!
DatabaseHandler.unmarshallingFailure=Loading of CityObject {} from embedded database failed! DatabaseHandler.unmarshallingFailure=Loading of CityObject {} from embedded database failed!
DatabaseSettings.invalidPath=Properties for database directory and name do not combine to a valid path. Using default value instead
DatabaseSettings.poolSizeLessThanOne=ConnectionPoolSize property was set to be less than 1. Using default value instead
DatabaseSettings.poolSizeNaN=ConnectionPoolSize property is not an integer. Using default value instead
DistanceError.distanceFromPlane=distance from plane DistanceError.distanceFromPlane=distance from plane
ErrorItemVisitor.childId=Child id ErrorItemVisitor.childId=Child id
ErrorItemVisitor.component=Component ErrorItemVisitor.component=Component
......
...@@ -6,15 +6,18 @@ CheckContainer.error=Unerwarteter Fehler bei der Ausf\u00fchrung von Pr\u00fcfun ...@@ -6,15 +6,18 @@ CheckContainer.error=Unerwarteter Fehler bei der Ausf\u00fchrung von Pr\u00fcfun
CheckDialog.availableChecksLabel=Verf\u00fcgbare Pr\u00fcfungen CheckDialog.availableChecksLabel=Verf\u00fcgbare Pr\u00fcfungen
CheckDialog.cancelBtn=Abbrechen CheckDialog.cancelBtn=Abbrechen
CheckDialog.checkBtn=Pr\u00fcfen CheckDialog.checkBtn=Pr\u00fcfen
CheckDialog.checkDescriptionsLabel=Beschreibungen der Pr\u00fcfungen sind auf der CityDoctor Homepage verf\u00fcgbar
CheckDialog.checkEnabled=Aktiv CheckDialog.checkEnabled=Aktiv
CheckDialog.checkName=Name CheckDialog.checkName=Name
CheckDialog.checksDone=Pr\u00fcfung abgeschlossen CheckDialog.checksDone=Pr\u00fcfung abgeschlossen
CheckDialog.checksReenabledAlert=Manche Pr\u00fcfungen wurden reaktiviert damit andere gewollte Pr\u00fcfungen durchgef\u00fchrt werden k\u00f6nnen\nMehr Details sind im Log geschrieben CheckDialog.checksReenabledAlert=Manche Pr\u00fcfungen wurden reaktiviert damit andere gewollte Pr\u00fcfungen durchgef\u00fchrt werden k\u00f6nnen\nMehr Details sind im Log geschrieben
CheckDialog.checksTab=Pr\u00fcfungen CheckDialog.checksTab=Pr\u00fcfungen
CheckDialog.clickHereToOpen=[Hier Klicken zum \u00d6ffnen]
CheckDialog.failedChecks=Konnte Pr\u00fcfungen nicht ausf\u00fchren CheckDialog.failedChecks=Konnte Pr\u00fcfungen nicht ausf\u00fchren
CheckDialog.filterTab=Filter CheckDialog.filterTab=Filter
CheckDialog.geometricChecksLabel=Geometrische Pr\u00fcfungen CheckDialog.geometricChecksLabel=Geometrische Pr\u00fcfungen
CheckDialog.globalParametersLabel=Globale Parameter CheckDialog.globalParametersLabel=Globale Parameter
CheckDialog.homepageHyperlink=https://transfer.hft-stuttgart.de/pages/citydoctor/citydoctorhomepage/de/requirements/
CheckDialog.noPathError=Ausgabepfad wurde nicht gesetzt! CheckDialog.noPathError=Ausgabepfad wurde nicht gesetzt!
CheckDialog.outputPathBtn=Ausw\u00e4hlen CheckDialog.outputPathBtn=Ausw\u00e4hlen
CheckDialog.outputPathLabel=Ausgabeordner (Pflichtfeld): CheckDialog.outputPathLabel=Ausgabeordner (Pflichtfeld):
...@@ -25,12 +28,14 @@ CheckDialog.schematronChooserTitle=W\u00e4hle Schematron Datei ... ...@@ -25,12 +28,14 @@ CheckDialog.schematronChooserTitle=W\u00e4hle Schematron Datei ...
CheckDialog.schematronFileLabel=Schematron Datei: CheckDialog.schematronFileLabel=Schematron Datei:
CheckDialog.schematronFileNotExisting=Schematron Datei existiert nicht, Schematron-Pr\u00fcfung wird \u00fcbersprungen CheckDialog.schematronFileNotExisting=Schematron Datei existiert nicht, Schematron-Pr\u00fcfung wird \u00fcbersprungen
CheckDialog.schematronFiles=Schematron Dateien CheckDialog.schematronFiles=Schematron Dateien
CheckDialog.selectAllChecksBtn=Alle aktivieren
CheckDialog.selectBtn=Ausw\u00e4hlen CheckDialog.selectBtn=Ausw\u00e4hlen
CheckDialog.semanticChecksLabel=Semantische Pr\u00fcfungen CheckDialog.semanticChecksLabel=Semantische Pr\u00fcfungen
CheckDialog.startingChecks=Starte Pr\u00fcfung CheckDialog.startingChecks=Starte Pr\u00fcfung
CheckDialog.streamCheckLabel=Stadtmodelle werden nicht in den Arbeitsspeicher geladen. Ergebnisse werden in der QualityADE in Kopien der Eingangsdateien gespeichert. CheckDialog.streamCheckLabel=Stadtmodelle werden nicht in den Arbeitsspeicher geladen. Ergebnisse werden in der QualityADE in Kopien der Eingangsdateien gespeichert.
CheckDialog.streamCheckOption=Niedrigen Arbeitsspeicherverbrauchsmodus aktivieren CheckDialog.streamCheckOption=Niedrigen Arbeitsspeicherverbrauchsmodus aktivieren
CheckDialog.title=Pr\u00fcfungskonfiguration CheckDialog.title=Pr\u00fcfungskonfiguration
CheckDialog.unselectAllChecksBtn=Alle deaktivieren
CheckDialog.validationConfiguration=Validierungskonfiguration CheckDialog.validationConfiguration=Validierungskonfiguration
CheckDialog.xmlReportsOption=XML-Berichte erstellen CheckDialog.xmlReportsOption=XML-Berichte erstellen
Checker.checkFeature=Pr\u00fcfe Feature: {} Checker.checkFeature=Pr\u00fcfe Feature: {}
...@@ -70,6 +75,9 @@ CityDoctorValidation.notExactlyOneOutputFile=Es muss exakt ein Ausgabedateipfad ...@@ -70,6 +75,9 @@ CityDoctorValidation.notExactlyOneOutputFile=Es muss exakt ein Ausgabedateipfad
CityDoctorValidation.notExactlyOnePDFOutput=Es muss exakt ein Ausgabedateipfad f\u00fcr den PDF-Bericht angegeben werden. CityDoctorValidation.notExactlyOnePDFOutput=Es muss exakt ein Ausgabedateipfad f\u00fcr den PDF-Bericht angegeben werden.
CityDoctorValidation.notExactlyOneXMLOutput=Es muss exakt ein Ausgabedateipfad f\u00fcr den XML-Bericht angegeben werden. CityDoctorValidation.notExactlyOneXMLOutput=Es muss exakt ein Ausgabedateipfad f\u00fcr den XML-Bericht angegeben werden.
CityDoctorValidation.wrongInputFileFormat=Eingabedatei '{}' ist keine .gml oder .xml Datei. CityDoctorValidation.wrongInputFileFormat=Eingabedatei '{}' ist keine .gml oder .xml Datei.
CityGmlFeatureMapper.crossFeatureReferencesDetected=Modell enth\u00e4lt Features mit Feature\u00fcbergreifenden Polygonreferenzen ohne eigene Duplikate
CityGmlFeatureMapper.emptyCrossFeatureReference=Polygon {} in Feature {} wird Feature\u00fcbergreifend referenziert durch Features: {}
CityGmlFeatureMapper.unresolvedReferencesDetected=Modell enth\u00e4lt Features mit Polygonreferenzen welche nicht aufgel\u00f6st werden konnten
CityGmlParser.chunkReadFailed=Konnte Datei nicht in St\u00fccken lesen, versuche komplett zu lesen CityGmlParser.chunkReadFailed=Konnte Datei nicht in St\u00fccken lesen, versuche komplett zu lesen
CityGmlParser.convertCrsToUtmZoneN=Konvertiere Koordinatensystem zu UTM Zone {}N CityGmlParser.convertCrsToUtmZoneN=Konvertiere Koordinatensystem zu UTM Zone {}N
CityGmlParser.convertCrsToUtmZoneS=Konvertiere Koordinatensystem zu UTM Zone {}S CityGmlParser.convertCrsToUtmZoneS=Konvertiere Koordinatensystem zu UTM Zone {}S
...@@ -99,6 +107,9 @@ DatabaseHandler.serializationFailure=Serialisierung des CityObject {} fehlgeschl ...@@ -99,6 +107,9 @@ DatabaseHandler.serializationFailure=Serialisierung des CityObject {} fehlgeschl
DatabaseHandler.setupFailure=KRITISCHER FEHLER: Erstellen der eingebetteten Datenbank fehlgeschlagen! DatabaseHandler.setupFailure=KRITISCHER FEHLER: Erstellen der eingebetteten Datenbank fehlgeschlagen!
DatabaseHandler.tableFailure=KRITISCHER FEHLER: Erstellen der "features" Tabelle fehlgeschlagen! DatabaseHandler.tableFailure=KRITISCHER FEHLER: Erstellen der "features" Tabelle fehlgeschlagen!
DatabaseHandler.unmarshallingFailure=Laden des CityObject {} aus der Datenbank fehlgeschlagen! DatabaseHandler.unmarshallingFailure=Laden des CityObject {} aus der Datenbank fehlgeschlagen!
DatabaseSettings.invalidPath=Einstellungen f\u00fcr Directory und Name der Datenbank bilden keinen validen Pfad. Standardwerte werden stattdessen genutzt
DatabaseSettings.poolSizeLessThanOne=ConnectionPoolSize Einstellung wurde auf unter 1 gesetzt. Standardwert wird stattdessen genutzt
DatabaseSettings.poolSizeNaN=ConnectionPoolSize Einstellung ist kein Integer. Standardwert wird stattdessen genutzt
DistanceError.distanceFromPlane=Abstand von der Ebene DistanceError.distanceFromPlane=Abstand von der Ebene
ErrorItemVisitor.childId=Kind ID ErrorItemVisitor.childId=Kind ID
ErrorItemVisitor.component=Komponente ErrorItemVisitor.component=Komponente
......
package de.hft.stuttgart.citydoctor2.database;
import org.junit.jupiter.api.Test;
public class DatabaseSettingsTest {
public void testSetLocation(){
String tempdirectory = System.getProperty("java.io.tmpdir");
DatabaseSettings.setDBLocation(tempdirectory + "/citydoctor");
}
}
...@@ -16,7 +16,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; ...@@ -16,7 +16,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.citygml4j.core.model.building.AbstractBuilding; import org.citygml4j.core.model.building.AbstractBuilding;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
...@@ -25,25 +24,44 @@ import java.util.List; ...@@ -25,25 +24,44 @@ import java.util.List;
import static de.hft.stuttgart.citydoctor2.database.SerializationTest.assertCityObjectEquality; import static de.hft.stuttgart.citydoctor2.database.SerializationTest.assertCityObjectEquality;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class EmbeddedDataBaseHandlerTest { public class EmbeddedDataBaseHandlerTest {
private EmbeddedDatabaseHandler handler; private final EmbeddedDatabaseHandler handler = new EmbeddedDatabaseHandler(new EmbeddedDatabaseConfiguration());
@Test
public void testTempFileConfiguration(){
EmbeddedDatabaseConfiguration tempFileconfig = new EmbeddedDatabaseConfiguration("database",
"inTempConfig",1, false,false,
false,true);
EmbeddedDatabaseHandler tempHandler = new EmbeddedDatabaseHandler(tempFileconfig);
assertTrue(tempHandler.getTempFileDBLocation().exists());
@Before
public void resetDatabase() {
try {
handler = new EmbeddedDatabaseHandler();
handler.setupFeaturesTable();
} catch (Exception e) {
fail(e.getMessage());
}
} }
@Test
public void testInMemoryConfiguration() throws CityGmlParseException, InvalidGmlFileException {
EmbeddedDatabaseConfiguration inMemoryConfig = new EmbeddedDatabaseConfiguration("database",
"irrelevant",1, true,false,
false,false);
EmbeddedDatabaseHandler memHandler = new EmbeddedDatabaseHandler(inMemoryConfig);
assertNull(memHandler.getTempFileDBLocation());
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = CityGmlParser.nestedCityGmlFileParse("src/test/resources/SimpleSolid_SrefBS.gml", config);
Building b = model.getBuildings().toList().get(0);
assertEquals(0, memHandler.getFeatureCount());
memHandler.marshallCityObject(b);
assertEquals(1, memHandler.getFeatureCount());
CityObject co = memHandler.unmarshallCityObject(b.getGmlId());
assertNotNull(co);
assertTrue(co instanceof Building);
}
@Test @Test
public void testGetBboxIntersectingObjects() { public void testGetBboxIntersectingObjects() {
handler.setupFeaturesTable();
Building b = new Building(); Building b = new Building();
Building b2 = new Building(); Building b2 = new Building();
b2.setGmlObject(Mockito.mock(AbstractBuilding.class)); b2.setGmlObject(Mockito.mock(AbstractBuilding.class));
...@@ -124,6 +142,7 @@ public class EmbeddedDataBaseHandlerTest { ...@@ -124,6 +142,7 @@ public class EmbeddedDataBaseHandlerTest {
@Test @Test
public void testGetBboxBufferIntersectingObjects() { public void testGetBboxBufferIntersectingObjects() {
handler.setupFeaturesTable();
Building b = new Building(); Building b = new Building();
Building b2 = new Building(); Building b2 = new Building();
b2.setGmlObject(Mockito.mock(AbstractBuilding.class)); b2.setGmlObject(Mockito.mock(AbstractBuilding.class));
...@@ -210,6 +229,7 @@ public class EmbeddedDataBaseHandlerTest { ...@@ -210,6 +229,7 @@ public class EmbeddedDataBaseHandlerTest {
Building b = model.getBuildings().toList().get(0); Building b = model.getBuildings().toList().get(0);
assertNotNull(b); assertNotNull(b);
assertEquals(1, handler.getFeatureCount());
handler.marshallCityObject(b); handler.marshallCityObject(b);
assertEquals(1, handler.getFeatureCount()); assertEquals(1, handler.getFeatureCount());
......
...@@ -90,8 +90,8 @@ public class ImplicitGeometryTest { ...@@ -90,8 +90,8 @@ public class ImplicitGeometryTest {
assertFalse(lib.containsError(CheckId.C_GE_P_NON_PLANAR)); assertFalse(lib.containsError(CheckId.C_GE_P_NON_PLANAR));
igh.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, mock(CheckError.class))); igh.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, mock(CheckError.class)));
assertFalse("ImplicitGeometryHolder's errors should be ignored and delegate the call to the prototype geometry", assertFalse(lib.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
lib.containsError(CheckId.C_GE_P_HOLE_OUTSIDE)); assertTrue(igh.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, mock(CheckError.class))); lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, mock(CheckError.class)));
assertTrue(lib.containsError(CheckId.C_GE_P_HOLE_OUTSIDE)); assertTrue(lib.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
...@@ -105,27 +105,39 @@ public class ImplicitGeometryTest { ...@@ -105,27 +105,39 @@ public class ImplicitGeometryTest {
@Test @Test
public void testClearAllContainedCheckResults() { public void testClearAllContainedCheckResults() {
igh.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null));
lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null)); lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null));
assertEquals(1, lib.getAllCheckResults().size()); assertEquals(1, lib.getAllCheckResults().size());
assertEquals(1, igh.getAllCheckResults().size());
lib.clearAllContainedCheckResults(); lib.clearAllContainedCheckResults();
assertTrue(lib.getAllCheckResults().isEmpty()); assertTrue(lib.getAllCheckResults().isEmpty());
assertEquals(1, igh.getAllCheckResults().size());
igh.clearAllContainedCheckResults();
assertTrue(igh.getAllCheckResults().isEmpty());
} }
@Test @Test
public void testContainsAnyError() { public void testContainsAnyError() {
assertFalse(lib.containsAnyError()); assertFalse(lib.containsAnyError());
assertFalse(igh.containsAnyError());
igh.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null)); igh.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null));
assertFalse(lib.containsAnyError()); assertFalse(lib.containsAnyError());
assertFalse(igh.containsAnyError());
lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null)); lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.OK, null));
assertFalse(lib.containsAnyError()); assertFalse(lib.containsAnyError());
assertFalse(igh.containsAnyError());
igh.addCheckResult( igh.addCheckResult(
new CheckResult(CheckId.C_GE_P_INNER_RINGS_NESTED, ResultStatus.ERROR, mock(CheckError.class))); new CheckResult(CheckId.C_GE_P_INNER_RINGS_NESTED, ResultStatus.ERROR, mock(CheckError.class)));
assertFalse(lib.containsAnyError()); assertFalse(lib.containsAnyError());
assertTrue(igh.containsAnyError());
lib.addCheckResult( lib.addCheckResult(
new CheckResult(CheckId.C_GE_P_INNER_RINGS_NESTED, ResultStatus.ERROR, mock(CheckError.class))); new CheckResult(CheckId.C_GE_P_INNER_RINGS_NESTED, ResultStatus.ERROR, mock(CheckError.class)));
assertTrue(lib.containsAnyError()); assertTrue(lib.containsAnyError());
assertTrue(igh.containsAnyError());
} }
@Test @Test
...@@ -134,19 +146,18 @@ public class ImplicitGeometryTest { ...@@ -134,19 +146,18 @@ public class ImplicitGeometryTest {
igh.addCheckResult(new CheckResult(CheckId.C_GE_P_NON_PLANAR, ResultStatus.ERROR, mock(CheckError.class))); igh.addCheckResult(new CheckResult(CheckId.C_GE_P_NON_PLANAR, ResultStatus.ERROR, mock(CheckError.class)));
igh.collectContainedErrors(errors); igh.collectContainedErrors(errors);
assertEquals("ImplicitGeometryHolder's errors should be ignored and delegate the call to the prototype geometry", assertEquals(1, errors.size());
0, errors.size()); errors.clear();
lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, mock(CheckError.class))); lib.addCheckResult(new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, mock(CheckError.class)));
igh.collectContainedErrors(errors); igh.collectContainedErrors(errors);
assertEquals("ImplicitGeometryHolder's errors should be ignored and delegate the call to the prototype geometry", assertEquals(1, errors.size());
1, errors.size());
} }
@Test @Test
public void testAccept() { public void testAccept() {
int polyCount = lib.getPolygons().size(); int polyCount = igh.getPolygons().size();
AtomicInteger loCounter = new AtomicInteger(0); AtomicInteger loCounter = new AtomicInteger(0);
...@@ -157,7 +168,7 @@ public class ImplicitGeometryTest { ...@@ -157,7 +168,7 @@ public class ImplicitGeometryTest {
} }
}; };
igh.accept(c); igh.accept(c);
assertEquals("ImplicitGeometryHolder should only check polygons of prototype geometry", assertEquals("Visitors should only walk over ImplicitGeometryHolder",
polyCount, loCounter.intValue()); polyCount, loCounter.intValue());
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>de.hft.stuttgart</groupId> <groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId> <artifactId>CityDoctorParent</artifactId>
<version>3.18.1</version> <version>3.18.2</version>
</parent> </parent>
<artifactId>CityDoctorValidation</artifactId> <artifactId>CityDoctorValidation</artifactId>
<name>CityDoctorValidation</name> <name>CityDoctorValidation</name>
......
#!/bin/sh #!/bin/sh
./runtime/bin/java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml ./runtime/bin/java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml -db_location "${TMPDIR:-/tmp}"
\ No newline at end of file \ No newline at end of file
java -classpath app/*;plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml java -classpath app/*;plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml -db_location %TEMP%/citydoctor/
pause pause
\ No newline at end of file
#!/bin/sh #!/bin/sh
java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml -db_location #!/bin/sh
\ No newline at end of file ./runtime/bin/java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml -db_location "${TMPDIR:-/tmp}"
\ No newline at end of file
"runtime/bin/java.exe" -classpath app/*;plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml "runtime/bin/java.exe" -classpath app/*;plugin/* de.hft.stuttgart.citydoctor2.CityDoctorValidation -in REKaiserwall.gml -config testConfigWithStreaming.yml -xmlReport output.xml -db_location %TEMP%/citydoctor/
pause pause
\ No newline at end of file
...@@ -23,6 +23,7 @@ import java.io.FileNotFoundException; ...@@ -23,6 +23,7 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import de.hft.stuttgart.citydoctor2.database.DatabaseSettings;
import de.hft.stuttgart.citydoctor2.utils.Localization; import de.hft.stuttgart.citydoctor2.utils.Localization;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -70,6 +71,8 @@ public class CityDoctorValidation { ...@@ -70,6 +71,8 @@ public class CityDoctorValidation {
String xmlOutput = getXmlOutput(argParser); String xmlOutput = getXmlOutput(argParser);
String pdfOutput = getPdfOutput(argParser); String pdfOutput = getPdfOutput(argParser);
String outputFile = getOutputFile(argParser, true); String outputFile = getOutputFile(argParser, true);
lookForDbConfigFileParameter(argParser);
lookForDbLocationParameter(argParser);
ValidationConfiguration config = getValidationConfig(argParser); ValidationConfiguration config = getValidationConfig(argParser);
startValidationProcess(inputFile, xmlOutput, pdfOutput, config, outputFile); startValidationProcess(inputFile, xmlOutput, pdfOutput, config, outputFile);
...@@ -81,18 +84,42 @@ public class CityDoctorValidation { ...@@ -81,18 +84,42 @@ public class CityDoctorValidation {
if (optional) { if (optional) {
return null; return null;
} }
logger.error(Localization.getText("CityDoctorValidation.noOutputFile")); logger.fatal(Localization.getText("CityDoctorValidation.noOutputFile"));
System.exit(11); System.exit(11);
} }
List<String> outFiles = argParser.getValues("out"); List<String> outFiles = argParser.getValues("out");
if (outFiles.size() != 1) { if (outFiles.size() != 1) {
logger.error(Localization.getText("CityDoctorValidation.notExactlyOneOutputFile")); logger.fatal(Localization.getText("CityDoctorValidation.notExactlyOneOutputFile"));
System.exit(12); System.exit(12);
} }
outputFile = outFiles.get(0); outputFile = outFiles.get(0);
return outputFile; return outputFile;
} }
private static void lookForDbConfigFileParameter(ArgumentParser argParser) {
if (!argParser.containsOption("db_config")) {
return;
}
List<String> dbConfigFiles = argParser.getValues("db_config");
if (dbConfigFiles.size() == 1) {
DatabaseSettings.loadPropertiesFromFile(new File(dbConfigFiles.get(0)));
} else if (dbConfigFiles.size() > 1) {
logger.warn("More than one DB config file provided! Using standard config instead.");
}
}
private static void lookForDbLocationParameter(ArgumentParser argParser) {
if (!argParser.containsOption("db_location")) {
return;
}
List<String> dbLocations = argParser.getValues("db_location");
if (dbLocations.size() == 1) {
DatabaseSettings.setDBLocation(dbLocations.get(0));
} else if (dbLocations.size() > 1) {
logger.warn("More than one DB location provided! Using standard location instead.");
}
}
/** /**
* Validates the cityGML input file with a standard validation configuration. * Validates the cityGML input file with a standard validation configuration.
* *
...@@ -202,7 +229,7 @@ public class CityDoctorValidation { ...@@ -202,7 +229,7 @@ public class CityDoctorValidation {
if (argParser.containsOption("pdfreport")) { if (argParser.containsOption("pdfreport")) {
List<String> reportFiles = argParser.getValues("pdfreport"); List<String> reportFiles = argParser.getValues("pdfreport");
if (reportFiles.size() != 1) { if (reportFiles.size() != 1) {
logger.error(Localization.getText("CityDoctorValidation.notExactlyOnePDFOutput")); logger.fatal(Localization.getText("CityDoctorValidation.notExactlyOnePDFOutput"));
System.exit(6); System.exit(6);
} }
return reportFiles.get(0); return reportFiles.get(0);
...@@ -214,7 +241,7 @@ public class CityDoctorValidation { ...@@ -214,7 +241,7 @@ public class CityDoctorValidation {
if (argParser.containsOption("xmlreport")) { if (argParser.containsOption("xmlreport")) {
List<String> reportFiles = argParser.getValues("xmlreport"); List<String> reportFiles = argParser.getValues("xmlreport");
if (reportFiles.size() != 1) { if (reportFiles.size() != 1) {
logger.error(Localization.getText("CityDoctorValidation.notExactlyOneXMLOutput")); logger.fatal(Localization.getText("CityDoctorValidation.notExactlyOneXMLOutput"));
System.exit(5); System.exit(5);
} }
return reportFiles.get(0); return reportFiles.get(0);
...@@ -231,7 +258,7 @@ public class CityDoctorValidation { ...@@ -231,7 +258,7 @@ public class CityDoctorValidation {
if (argParser.containsOption("config")) { if (argParser.containsOption("config")) {
List<String> configFiles = argParser.getValues("config"); List<String> configFiles = argParser.getValues("config");
if (configFiles.size() != 1) { if (configFiles.size() != 1) {
logger.error(Localization.getText("CityDoctorValidation.notExactlyOneConfigFile")); logger.fatal(Localization.getText("CityDoctorValidation.notExactlyOneConfigFile"));
System.exit(4); System.exit(4);
} }
return ValidationConfiguration.loadValidationConfigFile(configFiles.get(0)); return ValidationConfiguration.loadValidationConfigFile(configFiles.get(0));
...@@ -240,7 +267,7 @@ public class CityDoctorValidation { ...@@ -240,7 +267,7 @@ public class CityDoctorValidation {
logger.warn(Localization.getText("CityDoctorValidation.loadingDefaultConfig")); logger.warn(Localization.getText("CityDoctorValidation.loadingDefaultConfig"));
return ValidationConfiguration.loadStandardValidationConfig(); return ValidationConfiguration.loadStandardValidationConfig();
} else { } else {
logger.error(Localization.getText("CityDoctorValidation.noConfig")); logger.fatal(Localization.getText("CityDoctorValidation.noConfig"));
System.exit(7); System.exit(7);
return null; return null;
} }
...@@ -252,7 +279,7 @@ public class CityDoctorValidation { ...@@ -252,7 +279,7 @@ public class CityDoctorValidation {
if (argParser.containsOption("out")) { if (argParser.containsOption("out")) {
List<String> outFiles = argParser.getValues("out"); List<String> outFiles = argParser.getValues("out");
if (outFiles.size() != 1) { if (outFiles.size() != 1) {
logger.error(Localization.getText("CityDoctorValidation.multipleOutputFiles")); logger.fatal(Localization.getText("CityDoctorValidation.multipleOutputFiles"));
System.exit(3); System.exit(3);
} }
return outFiles.get(0); return outFiles.get(0);
...@@ -271,12 +298,12 @@ public class CityDoctorValidation { ...@@ -271,12 +298,12 @@ public class CityDoctorValidation {
if (optional) { if (optional) {
return null; return null;
} }
logger.error(Localization.getText("CityDoctorValidation.noInputFile")); logger.fatal(Localization.getText("CityDoctorValidation.noInputFile"));
System.exit(1); System.exit(1);
} }
List<String> inFiles = argParser.getValues("in"); List<String> inFiles = argParser.getValues("in");
if (inFiles.size() != 1) { if (inFiles.size() != 1) {
logger.error(Localization.getText("CityDoctorValidation.notExactlyOneInputFile")); logger.fatal(Localization.getText("CityDoctorValidation.notExactlyOneInputFile"));
System.exit(2); System.exit(2);
} }
inputFile = inFiles.get(0); inputFile = inFiles.get(0);
......
...@@ -2,6 +2,7 @@ package de.hft.stuttgart.citydoctor2; ...@@ -2,6 +2,7 @@ package de.hft.stuttgart.citydoctor2;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.database.DatabaseSettings;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
...@@ -26,20 +27,30 @@ public class CityDoctorValidationCLI implements Runnable { ...@@ -26,20 +27,30 @@ public class CityDoctorValidationCLI implements Runnable {
private File config; private File config;
@Option(names = {"-x" , "--xml" , "--xmlReport"}, @Option(names = {"-x" , "--xml" , "--xmlReport"},
description = "Create a XML validation report at target location", description = "Creates a XML validation report at target location",
defaultValue = Option.NULL_VALUE) defaultValue = Option.NULL_VALUE)
private String xmlReport; private String xmlReport;
@Option(names = {"-p" , "--pdf" , "--pdfReport"}, @Option(names = {"-p" , "--pdf" , "--pdfReport"},
description = "Create a PDF validation report at target location", description = "Creates a PDF validation report at target location",
defaultValue = Option.NULL_VALUE) defaultValue = Option.NULL_VALUE)
private String pdfReport; private String pdfReport;
@Option(names = {"-o" , "--out" , "--output"}, @Option(names = {"-o" , "--out" , "--output"},
description = "Create a validated copy of the CityGML input with QualityADE at target location.", description = "Creates a validated copy of the CityGML input with QualityADE at target location.",
defaultValue = Option.NULL_VALUE) defaultValue = Option.NULL_VALUE)
private String output; private String output;
@Option(names = {"--db_location", "--db_loc"},
description = "Creates the embedded database file at target location instead of CityDoctor's working directory.",
defaultValue = Option.NULL_VALUE)
private String dbLocation;
@Option(names = {"-db", "--db_config", "--db_settings"},
description = "Filepath to a .properties file for overriding the default configuration of the embedded database",
defaultValue = Option.NULL_VALUE)
private String dbConfig;
@Override @Override
public void run(){ public void run(){
try { try {
...@@ -49,6 +60,12 @@ public class CityDoctorValidationCLI implements Runnable { ...@@ -49,6 +60,12 @@ public class CityDoctorValidationCLI implements Runnable {
} else{ } else{
valConfig=ValidationConfiguration.loadValidationConfigFile(config.getAbsolutePath()); valConfig=ValidationConfiguration.loadValidationConfigFile(config.getAbsolutePath());
} }
if(dbConfig != null){
DatabaseSettings.loadPropertiesFromFile(new File(dbConfig));
}
if (dbLocation != null) {
DatabaseSettings.setDBLocation(dbLocation);
}
CityDoctorValidation.startValidationProcess(input, xmlReport, pdfReport, valConfig,output); CityDoctorValidation.startValidationProcess(input, xmlReport, pdfReport, valConfig,output);
} catch (CityDoctorWriteException | CityGmlParseException | IOException | InvalidGmlFileException e) { } catch (CityDoctorWriteException | CityGmlParseException | IOException | InvalidGmlFileException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
......
...@@ -47,6 +47,7 @@ import java.util.concurrent.ThreadPoolExecutor; ...@@ -47,6 +47,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.transform.Result; import javax.xml.transform.Result;
import javax.xml.transform.Source; import javax.xml.transform.Source;
...@@ -77,7 +78,6 @@ import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; ...@@ -77,7 +78,6 @@ import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId; import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder;
import de.hft.stuttgart.citydoctor2.parser.CityGmlConsumer; import de.hft.stuttgart.citydoctor2.parser.CityGmlConsumer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
...@@ -150,8 +150,8 @@ public class Checker { ...@@ -150,8 +150,8 @@ public class Checker {
return; return;
} }
File xmlFile = new File(xmlOutput); File xmlFile = new File(xmlOutput);
if (xmlFile.getParentFile() != null) { if (xmlFile.getParentFile() != null && xmlFile.getParentFile().mkdirs()) {
xmlFile.getParentFile().mkdirs(); logger.trace("Xml dir created");
} }
Reporter reporter = new XmlValidationReporter(); Reporter reporter = new XmlValidationReporter();
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(xmlFile.getAbsolutePath()))) { try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(xmlFile.getAbsolutePath()))) {
...@@ -166,9 +166,10 @@ public class Checker { ...@@ -166,9 +166,10 @@ public class Checker {
return; return;
} }
File pdfFile = new File(pdfOutput); File pdfFile = new File(pdfOutput);
if (pdfFile.getParentFile() != null) { if (pdfFile.getParentFile() != null && pdfFile.getParentFile().mkdirs()){
pdfFile.getParentFile().mkdirs(); logger.trace("Pdf dir created");
} }
Reporter reporter = new PdfReporter(); Reporter reporter = new PdfReporter();
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pdfFile.getAbsolutePath()))) { try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pdfFile.getAbsolutePath()))) {
reporter.writeReport(checkConfig, bos, model, config); reporter.writeReport(checkConfig, bos, model, config);
...@@ -243,7 +244,6 @@ public class Checker { ...@@ -243,7 +244,6 @@ public class Checker {
private void handleSchematronResults(SvrlContentHandler handler) { private void handleSchematronResults(SvrlContentHandler handler) {
CityObjectCache cache = model.getCache(); CityObjectCache cache = model.getCache();
handleSchematronErrorsGlobal(handler.getGeneralErrors()); handleSchematronErrorsGlobal(handler.getGeneralErrors());
Map<String, CityObject> featureMap = new HashMap<>();
boolean onlySchematron = execLayers.isEmpty(); boolean onlySchematron = execLayers.isEmpty();
if (onlySchematron) { if (onlySchematron) {
CheckableUtilsVisitor visitor = new CheckableUtilsVisitor() { CheckableUtilsVisitor visitor = new CheckableUtilsVisitor() {
...@@ -252,12 +252,7 @@ public class Checker { ...@@ -252,12 +252,7 @@ public class Checker {
checkable.setValidated(true); checkable.setValidated(true);
} }
}; };
model.createFeatureStream().forEach(f -> { model.createFeatureStream().forEach(co -> co.accept(visitor));
featureMap.put(f.getGmlId().getGmlString(), f);
f.accept(visitor);
});
} else {
model.createFeatureStream().forEach(f -> featureMap.put(f.getGmlId().getGmlString(), f));
} }
handler.getFeatureErrors().forEach((k, v) -> { handler.getFeatureErrors().forEach((k, v) -> {
String trimmedId = k.trim(); String trimmedId = k.trim();
...@@ -708,12 +703,11 @@ public class Checker { ...@@ -708,12 +703,11 @@ public class Checker {
(threadCount, threadCount, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); (threadCount, threadCount, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
try{ try{
long startTime = System.nanoTime(); long startTime = System.nanoTime();
ImplicitGeometryHolder.preparePrototypeGeometriesForChecking();
List<Future<GmlId>> futures = runChecksOnFeatures(exec, cache, features, checkedCount, l); List<Future<GmlId>> futures = runChecksOnFeatures(exec, cache, features, checkedCount, l);
List<GmlId> missedFeatures = getMissedFeatures(futures); List<GmlId> missedFeatures = getMissedFeatures(futures);
ImplicitGeometryHolder.clearMetaDataOfPrototypeGeometries();
if (!missedFeatures.isEmpty()){ if (!missedFeatures.isEmpty()){
logger.error(Localization.getText("Checker.dbUnresponsive")); logger.error(Localization.getText("Checker.dbUnresponsive"));
if (logger.isDebugEnabled()){ if (logger.isDebugEnabled()){
...@@ -747,8 +741,22 @@ public class Checker { ...@@ -747,8 +741,22 @@ public class Checker {
} }
} }
/**
* Runs the validation on a list of Features. The checks are run asynchronously and multithreaded. Returns a list
* of {@link Future Futures} for evaluation if Features failed to be checked due to exceptions or failing to load from
* the cache. If failed, the respective Future will return the affected Feature's GmlID.
* <p>Checks finding an error in a Feature, or not having their dependencies met, are not a check-failure in this
* context.<p/>
* @param exec the threadpool for the tasks
* @param cache the cache of the model
* @param ids the list of GmlIds to check
* @param checkedCount the number of already checked Features for tracking the total progress of validation across retries
* @param l a listener for the progress of the validation, can be null
* @return a list of Futures containing the GmlId of Features that failed to execute all checks, and contain null otherwise
* @throws InterruptedException if interrupted while invoking the tasks for checking
*/
private List<Future<GmlId>> runChecksOnFeatures(ExecutorService exec, CityObjectCache cache, List<GmlId> ids, AtomicInteger checkedCount, private List<Future<GmlId>> runChecksOnFeatures(ExecutorService exec, CityObjectCache cache, List<GmlId> ids, AtomicInteger checkedCount,
ProgressListener l) @Nullable ProgressListener l)
throws InterruptedException { throws InterruptedException {
float featureSum = ids.size() + (float) checkedCount.get(); float featureSum = ids.size() + (float) checkedCount.get();
...@@ -762,11 +770,9 @@ public class Checker { ...@@ -762,11 +770,9 @@ public class Checker {
} }
if(Thread.interrupted()){ if(Thread.interrupted()){
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return null; return id;
} }
co.prepareForChecking();
executeChecksForCityObject(co); executeChecksForCityObject(co);
co.clearMetaInformation();
cache.put(co); cache.put(co);
checkedCount.incrementAndGet(); checkedCount.incrementAndGet();
if (l!=null){ if (l!=null){
...@@ -781,7 +787,7 @@ public class Checker { ...@@ -781,7 +787,7 @@ public class Checker {
private List<GmlId> getMissedFeatures(List<Future<GmlId>> futures) throws InterruptedException{ private List<GmlId> getMissedFeatures(List<Future<GmlId>> futures) throws InterruptedException{
List<GmlId> missedList = new ArrayList<>(); List<GmlId> missedList = new ArrayList<>();
Set<ExecutionException> errors = new HashSet<>(); Set<String> errors = new HashSet<>();
for (Future<GmlId> future : futures) { for (Future<GmlId> future : futures) {
try{ try{
GmlId gmlId = future.get(); GmlId gmlId = future.get();
...@@ -791,7 +797,7 @@ public class Checker { ...@@ -791,7 +797,7 @@ public class Checker {
} catch (ExecutionException e){ } catch (ExecutionException e){
logger.debug("A Task failed due to an unexpected exception", e); logger.debug("A Task failed due to an unexpected exception", e);
logger.debug(e.getCause()); logger.debug(e.getCause());
errors.add(e); errors.add(e.getCause().toString());
} }
} }
if (!errors.isEmpty()) { if (!errors.isEmpty()) {
...@@ -839,7 +845,9 @@ public class Checker { ...@@ -839,7 +845,9 @@ public class Checker {
if (!filterObject(co)) { if (!filterObject(co)) {
return; return;
} }
co.prepareForChecking();
executeChecksForCheckable(co); executeChecksForCheckable(co);
co.clearMetaInformation();
} }
/** /**
...@@ -938,7 +946,7 @@ public class Checker { ...@@ -938,7 +946,7 @@ public class Checker {
SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile); SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile);
CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, l); CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, l);
// parse and validate // parse and validate
CityGmlParser.streamCityGml(inputFile.getAbsolutePath(), config.getParserConfiguration(), con, outputFile); CityGmlParser.streamCityGml(inputFile, config.getParserConfiguration(), con, outputFile);
// write reports if available // write reports if available
writeReport(xmlReporter); writeReport(xmlReporter);
......
...@@ -20,7 +20,9 @@ package de.hft.stuttgart.citydoctor2.checks.util; ...@@ -20,7 +20,9 @@ package de.hft.stuttgart.citydoctor2.checks.util;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.IntStream;
public class CollectionUtils { public class CollectionUtils {
...@@ -40,4 +42,11 @@ public class CollectionUtils { ...@@ -40,4 +42,11 @@ public class CollectionUtils {
return set; return set;
} }
public static <T> List<List<T>> partition(List<T> list, int chunkSize){
return IntStream.iterate(0, i-> i < list.size(), i-> i+ chunkSize)
.mapToObj(i -> list.subList(i, Math.min(i+chunkSize, list.size())))
.toList();
}
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>de.hft.stuttgart</groupId> <groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId> <artifactId>CityDoctorParent</artifactId>
<version>3.18.1</version> <version>3.18.2</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<artifactId>CityDoctorAutoPro</artifactId> <artifactId>CityDoctorAutoPro</artifactId>
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>de.hft.stuttgart</groupId> <groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId> <artifactId>CityDoctorParent</artifactId>
<version>3.18.1</version> <version>3.18.2</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<artifactId>CityDoctorGUI</artifactId> <artifactId>CityDoctorGUI</artifactId>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment