Commit 5571f382 authored by Luna Riegel's avatar Luna Riegel
Browse files

Merge branch 'dev' into 'master'

CityDoctor Version 3.18.0

See merge request !37
parents 87dba3fa 61859d4f
Pipeline #12247 passed with stage
in 2 minutes and 31 seconds
...@@ -101,7 +101,7 @@ public class RingSelfIntersectionTest { ...@@ -101,7 +101,7 @@ public class RingSelfIntersectionTest {
@Test @Test
public void testSelfIntPoints4() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testSelfIntPoints4() throws CityGmlParseException, IOException, InvalidGmlFileException {
CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml"); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml");
for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) {
LinearRing r = p.getExteriorRing(); LinearRing r = p.getExteriorRing();
CheckResult cr = r.getCheckResult(CheckId.C_GE_R_SELF_INTERSECTION); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_SELF_INTERSECTION);
assertEquals(ResultStatus.OK, cr.getResultStatus()); assertEquals(ResultStatus.OK, cr.getResultStatus());
...@@ -131,7 +131,7 @@ public class RingSelfIntersectionTest { ...@@ -131,7 +131,7 @@ public class RingSelfIntersectionTest {
@Test @Test
public void testSelfIntPoints7() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testSelfIntPoints7() throws CityGmlParseException, IOException, InvalidGmlFileException {
CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml", 2); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml", 2);
for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) {
LinearRing r = p.getExteriorRing(); LinearRing r = p.getExteriorRing();
CheckResult cr = r.getCheckResult(CheckId.C_GE_R_SELF_INTERSECTION); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_SELF_INTERSECTION);
assertEquals(ResultStatus.OK, cr.getResultStatus()); assertEquals(ResultStatus.OK, cr.getResultStatus());
......
...@@ -43,7 +43,7 @@ public class ShellNotClosedSystemTest { ...@@ -43,7 +43,7 @@ public class ShellNotClosedSystemTest {
@Test @Test
public void testShellNotClosed1() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testShellNotClosed1() throws CityGmlParseException, IOException, InvalidGmlFileException {
CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml"); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml");
Geometry g = c.getBuildings().get(0).getGeometries().get(0); Geometry g = c.getBuildings().toList().get(0).getGeometries().get(0);
CheckResult cr = g.getCheckResult(CheckId.C_GE_S_NOT_CLOSED); CheckResult cr = g.getCheckResult(CheckId.C_GE_S_NOT_CLOSED);
assertEquals(ResultStatus.OK, cr.getResultStatus()); assertEquals(ResultStatus.OK, cr.getResultStatus());
} }
...@@ -51,7 +51,7 @@ public class ShellNotClosedSystemTest { ...@@ -51,7 +51,7 @@ public class ShellNotClosedSystemTest {
@Test @Test
public void testShellNotClosed2() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testShellNotClosed2() throws CityGmlParseException, IOException, InvalidGmlFileException {
CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml"); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml");
Geometry g = c.getBuildings().get(0).getGeometries().get(0); Geometry g = c.getBuildings().toList().get(0).getGeometries().get(0);
CheckResult cr = g.getCheckResult(CheckId.C_GE_S_NOT_CLOSED); CheckResult cr = g.getCheckResult(CheckId.C_GE_S_NOT_CLOSED);
assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId()); assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId());
......
...@@ -22,6 +22,7 @@ import java.io.IOException; ...@@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional;
import de.hft.stuttgart.citydoctor2.check.Checker; import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
...@@ -89,15 +90,16 @@ public class TestUtil { ...@@ -89,15 +90,16 @@ public class TestUtil {
if (gmlId == null) { if (gmlId == null) {
return null; return null;
} }
Polygon result = getPolygonById(gmlId, model.getBuildings()); Polygon result = getPolygonById(gmlId, model.getBuildings().toList());
if (result != null) { if (result != null) {
return result; return result;
} }
result = getPolygonById(gmlId, model.getVegetation()); result = getPolygonById(gmlId, model.getVegetation().toList());
if (result != null) { if (result != null) {
return result; return result;
} }
return getPolygonById(gmlId, model.getTransportation()); return getPolygonById(gmlId, model.getTransportation().toList());
} }
private static Polygon getPolygonById(String gmlId, List<? extends CityObject> features) { private static Polygon getPolygonById(String gmlId, List<? extends CityObject> features) {
...@@ -136,22 +138,17 @@ public class TestUtil { ...@@ -136,22 +138,17 @@ public class TestUtil {
if (featureId == null) { if (featureId == null) {
return null; return null;
} }
for (CityObject co : model.getBuildings()) { Optional<? extends CityObject> result = null;
if (featureId.equals(co.getGmlId().getGmlString())) { result = model.getBuildings().filter(b -> featureId.equals(b.getGmlId().toString())).findFirst();
return co; if (result.isPresent()){
} return result.get();
} }
for (CityObject co : model.getTransportation()) { result = model.getTransportation().filter(t-> featureId.equals(t.getGmlId().toString())).findFirst();
if (featureId.equals(co.getGmlId().getGmlString())) { if (result.isPresent()){
return co; return result.get();
}
} }
for (CityObject co : model.getVegetation()) { result = model.getVegetation().filter(t-> featureId.equals(t.getGmlId().toString())).findFirst();
if (featureId.equals(co.getGmlId().getGmlString())) { return result.orElse(null);
return co; }
}
}
return null;
}
} }
...@@ -43,7 +43,7 @@ public class TooFewPolygonsSystemTest { ...@@ -43,7 +43,7 @@ public class TooFewPolygonsSystemTest {
@Test @Test
public void testTooFewPolygons1() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testTooFewPolygons1() throws CityGmlParseException, IOException, InvalidGmlFileException {
CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml"); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml");
Geometry g = c.getBuildings().get(0).getGeometries().get(0); Geometry g = c.getBuildings().toList().get(0).getGeometries().get(0);
CheckResult cr = g.getCheckResult(CheckId.C_GE_S_TOO_FEW_POLYGONS); CheckResult cr = g.getCheckResult(CheckId.C_GE_S_TOO_FEW_POLYGONS);
assertEquals(ResultStatus.OK, cr.getResultStatus()); assertEquals(ResultStatus.OK, cr.getResultStatus());
} }
...@@ -51,7 +51,7 @@ public class TooFewPolygonsSystemTest { ...@@ -51,7 +51,7 @@ public class TooFewPolygonsSystemTest {
@Test @Test
public void testTooFewPolygons2() throws CityGmlParseException, IOException, InvalidGmlFileException { public void testTooFewPolygons2() throws CityGmlParseException, IOException, InvalidGmlFileException {
CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml"); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml");
Geometry g = c.getBuildings().get(0).getGeometries().get(0); Geometry g = c.getBuildings().toList().get(0).getGeometries().get(0);
CheckResult cr = g.getCheckResult(CheckId.C_GE_S_TOO_FEW_POLYGONS); CheckResult cr = g.getCheckResult(CheckId.C_GE_S_TOO_FEW_POLYGONS);
assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ResultStatus.ERROR, cr.getResultStatus());
assertEquals(ErrorId.GE_S_TOO_FEW_POLYGONS, cr.getError().getErrorId()); assertEquals(ErrorId.GE_S_TOO_FEW_POLYGONS, cr.getError().getErrorId());
......
...@@ -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.17.3</version> <version>3.18.0</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.17.3</version> <version>3.18.0</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<artifactId>CityDoctorGUI</artifactId> <artifactId>CityDoctorGUI</artifactId>
......
#!/bin/sh #! /usr/bin/env sh
./runtime/bin/java -classpath app/*:plugin/* de.hft.stuttgart.citydoctor2.gui.CityDoctorGUIStarter java -classpath "app/*:plugin/*" de.hft.stuttgart.citydoctor2.gui.CityDoctorGUIStarter
\ No newline at end of file
...@@ -11,6 +11,7 @@ import java.util.List; ...@@ -11,6 +11,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import de.hft.stuttgart.citydoctor2.parser.ProgressListener;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
...@@ -139,8 +140,6 @@ public class CheckDialog { ...@@ -139,8 +140,6 @@ public class CheckDialog {
@FXML @FXML
private Label schematronFileLabel; private Label schematronFileLabel;
@FXML
private VBox zipArchiveOptionsVBox;
@FXML @FXML
private CheckBox streamCheckOption; private CheckBox streamCheckOption;
@FXML @FXML
...@@ -161,7 +160,6 @@ public class CheckDialog { ...@@ -161,7 +160,6 @@ public class CheckDialog {
private CityDoctorController controller; private CityDoctorController controller;
private FilterPane filterPane; private FilterPane filterPane;
private MainWindow window; private MainWindow window;
private boolean zipArchiveMode;
public CheckDialog(MainWindow window, Window parent, CityDoctorController controller) throws IOException { public CheckDialog(MainWindow window, Window parent, CityDoctorController controller) throws IOException {
this.window = window; this.window = window;
...@@ -181,7 +179,6 @@ public class CheckDialog { ...@@ -181,7 +179,6 @@ public class CheckDialog {
} }
public void initialize() { public void initialize() {
setupZipArchiveOptions();
createEnableColumn(geometricTable); createEnableColumn(geometricTable);
createNameColumn(geometricTable); createNameColumn(geometricTable);
...@@ -286,46 +283,6 @@ public class CheckDialog { ...@@ -286,46 +283,6 @@ public class CheckDialog {
}); });
} }
private void setupZipArchiveOptions() {
streamCheckOption.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
streamCheckParametersVBox.setDisable(!streamCheckOption.isSelected());
}
});
outputPathBtn.setOnAction(e -> {
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setInitialDirectory(Path.of(Settings.get(Settings.LAST_OPEN_FOLDER)).getParent().toFile());
File f = directoryChooser.showDialog(stage.getOwner());
if (f != null) {
outputPathTextField.setText(f.getAbsolutePath());
Settings.set(Settings.LAST_OPEN_FOLDER, f.getAbsolutePath());
}
});
streamCheckOption.setText(Localization.getText("CheckDialog.streamCheckOption"));
streamCheckLabel.setTooltip(new Tooltip(Localization.getText("CheckDialog.streamCheckLabel")));
outputPathLabel.setText(Localization.getText("CheckDialog.outputPathLabel"));
outputPathBtn.setText(Localization.getText("CheckDialog.outputPathBtn"));
pdfReportsOption.setText(Localization.getText("CheckDialog.pdfReportsOption"));
xmlReportsOption.setText(Localization.getText("CheckDialog.xmlReportsOption"));
showZipArchiveOptions(false);
}
/**
* Shows the option panel for ZIP-Archive checking and enables the ZIP-Archive checking mode for this dialog.
*
* @param enabled
*/
public void showZipArchiveOptions(boolean enabled) {
zipArchiveOptionsVBox.setDisable(!enabled);
zipArchiveOptionsVBox.setVisible(enabled);
zipArchiveMode = enabled;
}
private void setupSelectButton() { private void setupSelectButton() {
selectBtn.setOnAction(ae -> { selectBtn.setOnAction(ae -> {
...@@ -494,25 +451,13 @@ public class CheckDialog { ...@@ -494,25 +451,13 @@ public class CheckDialog {
String startingChecks = Localization.getText("CheckDialog.startingChecks"); String startingChecks = Localization.getText("CheckDialog.startingChecks");
logger.info(startingChecks); logger.info(startingChecks);
} }
if (zipArchiveMode) { ProgressListener l = new ProgressListener() {
Path outputPath = null; @Override
if (streamCheckOption.isSelected()) { public void updateProgress(float state) {
if (outputPathTextField.getText().isEmpty()) { Platform.runLater(() -> progress.setProgress(state));
Alert warning = new Alert(Alert.AlertType.ERROR);
warning.setTitle("Error");
warning.setContentText(Localization.getText("CheckDialog.noPathError"));
warning.showAndWait();
return;
}
outputPath = Path.of(outputPathTextField.getText());
Platform.runLater(() -> progress.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS));
} }
controller.startZipFileChecks(config, progress::setProgress, streamCheckOption.isSelected(), };
outputPath, pdfReportsOption.isSelected(), controller.startChecks(config, l);
xmlReportsOption.isSelected());
} else {
controller.startChecks(config, progress::setProgress);
}
if (logger.isInfoEnabled()) { if (logger.isInfoEnabled()) {
String checksDone = Localization.getText("CheckDialog.checksDone"); String checksDone = Localization.getText("CheckDialog.checksDone");
......
...@@ -5,6 +5,7 @@ import de.hft.stuttgart.citydoctor2.check.Checker; ...@@ -5,6 +5,7 @@ import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId; import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError; import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.database.UnconnectedCache;
import de.hft.stuttgart.citydoctor2.datastructure.*; import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat; import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat;
...@@ -16,15 +17,11 @@ import de.hft.stuttgart.citydoctor2.gui.tree.node.OpeningNode; ...@@ -16,15 +17,11 @@ import de.hft.stuttgart.citydoctor2.gui.tree.node.OpeningNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.TopLevelCityObjectNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.TopLevelCityObjectNode;
import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler; import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler;
import de.hft.stuttgart.citydoctor2.parser.*; import de.hft.stuttgart.citydoctor2.parser.*;
import de.hft.stuttgart.citydoctor2.utils.ArchivePacker;
import de.hft.stuttgart.citydoctor2.utils.Localization; import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive; import de.hft.stuttgart.quality.adapter.types.ErrorAdapter;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
import de.hft.stuttgart.citydoctor2.zip.MalformedZipFileException;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.chart.XYChart.Data; import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series; import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType; import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog; import javafx.scene.control.Dialog;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
...@@ -32,22 +29,18 @@ import javafx.scene.control.TreeView; ...@@ -32,22 +29,18 @@ import javafx.scene.control.TreeView;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.FileChooser.ExtensionFilter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.core.CityModel; import org.citygml4j.core.model.core.CityModel;
import org.xml.sax.SAXParseException; import org.xml.sax.SAXParseException;
import java.awt.*;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class CityDoctorController { public class CityDoctorController {
...@@ -60,9 +53,7 @@ public class CityDoctorController { ...@@ -60,9 +53,7 @@ public class CityDoctorController {
private CityDoctorModel model; private CityDoctorModel model;
private ParserConfiguration currentConfig; private ParserConfiguration currentConfig;
private String sourceFile; private String sourceFile;
private CityGmlZipArchive zipArchive;
private ZipEntryManager currentZipEntryManager;
private HashMap<CityDoctorModel, Checker> previousCheckers = null;
private Checker currentChecker; private Checker currentChecker;
private HighlightController highlightController; private HighlightController highlightController;
...@@ -77,7 +68,9 @@ public class CityDoctorController { ...@@ -77,7 +68,9 @@ public class CityDoctorController {
private AtomicInteger waterChunkNr = new AtomicInteger(0); private AtomicInteger waterChunkNr = new AtomicInteger(0);
private AtomicInteger landChunkNr = new AtomicInteger(0); private AtomicInteger landChunkNr = new AtomicInteger(0);
private AtomicInteger cityFurnitureChunkNr = new AtomicInteger(0); private AtomicInteger cityFurnitureChunkNr = new AtomicInteger(0);
private AtomicInteger genericCityObjectsChunkNr = new AtomicInteger(0); private AtomicInteger otherCityObjectsChunkNr = new AtomicInteger(0);
public CityDoctorController(MainWindow mainWindow, HighlightController highlightController, Renderer renderer) { public CityDoctorController(MainWindow mainWindow, HighlightController highlightController, Renderer renderer) {
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
...@@ -95,7 +88,7 @@ public class CityDoctorController { ...@@ -95,7 +88,7 @@ public class CityDoctorController {
try { try {
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindow.getOpenBtn().setDisable(true); mainWindow.getOpenBtn().setDisable(true);
mainWindow.getZipManagerBtn().setDisable(true);
mainWindow.getWriteReportButton().setDisable(true); mainWindow.getWriteReportButton().setDisable(true);
mainWindow.getMeshGroup().getChildren().clear(); mainWindow.getMeshGroup().getChildren().clear();
...@@ -103,12 +96,6 @@ public class CityDoctorController { ...@@ -103,12 +96,6 @@ public class CityDoctorController {
mainWindow.resetSearchBar(); mainWindow.resetSearchBar();
mainWindow.resetFilterComboBox(); mainWindow.resetFilterComboBox();
}); });
if (path.endsWith(".zip")) {
loadCityGmlZipFile(path, numberOfRoundingPlaces, useValidation, lowMemory);
return;
}
currentZipEntryManager = null;
previousCheckers = null;
currentChecker = null; currentChecker = null;
currentConfig = new ParserConfiguration(numberOfRoundingPlaces, useValidation, lowMemory); currentConfig = new ParserConfiguration(numberOfRoundingPlaces, useValidation, lowMemory);
GMLValidationHandler handler = null; GMLValidationHandler handler = null;
...@@ -135,7 +122,7 @@ public class CityDoctorController { ...@@ -135,7 +122,7 @@ public class CityDoctorController {
} }
}; };
} }
model = CityGmlParser.parseCityGmlFile(path, currentConfig, l, handler, true); model = CityGmlParser.parseCityGmlFile(path, currentConfig, l, handler);
if (!validationIssues.isEmpty()) { if (!validationIssues.isEmpty()) {
StringJoiner sj = new StringJoiner("\n"); StringJoiner sj = new StringJoiner("\n");
validationIssues.stream().forEach(sj::add); validationIssues.stream().forEach(sj::add);
...@@ -155,120 +142,30 @@ public class CityDoctorController { ...@@ -155,120 +142,30 @@ public class CityDoctorController {
mainWindow.getSaveBtn().setDisable(false); mainWindow.getSaveBtn().setDisable(false);
mainWindow.getResetCameraBtn().setDisable(false); mainWindow.getResetCameraBtn().setDisable(false);
mainWindow.getHideRoofBtn().setDisable(false); mainWindow.getHideRoofBtn().setDisable(false);
mainWindow.getZipManagerBtn().setDisable(true);
mainWindow.getNorthArrow().setVisible(true);
mainWindow.alignNorthArrow();
setupFeatureTabs();
buildTrees();
});
} finally {
Platform.runLater(() -> mainWindow.getOpenBtn().setDisable(false));
}
}
private void loadCityGmlZipFile(String path, int numberOfRoundingPlaces, boolean useValidation,
boolean lowMemory) {
currentConfig = new ParserConfiguration(numberOfRoundingPlaces, useValidation, lowMemory);
try {
zipArchive = CityGmlZipArchive.register(path);
} catch (MalformedZipFileException e) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR, e.getMessage());
alert.showAndWait();
});
} catch (Exception e) {
Platform.runLater(() -> {
ExceptionDialog exDialog = new ExceptionDialog();
exDialog.show(e);
});
}
if (zipArchive != null) {
previousCheckers = new HashMap<>();
Platform.runLater(() -> {
try {
currentZipEntryManager = new ZipEntryManager(mainWindow.getMainStage(), this);
currentZipEntryManager.show();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
public void decompressZipEntry(CityGmlZipEntry entry, ProgressListener l) {
entry.loadEntry(currentConfig, l);
}
public CityGmlZipArchive getZipArchive() {
return zipArchive;
}
public void loadZipEntry(CityGmlZipEntry entry) {
if (!entry.isLoaded()) {
entry.loadEntry(currentConfig);
}
if (entry.getErrorType() != null) {
throw new IllegalArgumentException("Attempted to load erroneous zip entry");
}
try {
Platform.runLater(() -> {
mainWindow.getOpenBtn().setDisable(true);
mainWindow.getZipManagerBtn().setDisable(true);
mainWindow.getWriteReportButton().setDisable(true);
mainWindow.getMeshGroup().getChildren().clear();
clearTrees();
mainWindow.resetSearchBar();
mainWindow.resetFilterComboBox();
});
model = entry.getModel();
currentChecker = previousCheckers.getOrDefault(model, null);
mainWindow.getClickHandler().setConfig(currentConfig);
sourceFile = entry.getArchive().getArchivePath().toString();
renderer.reset();
Platform.runLater(() -> {
mainWindow.addFileNameToTitle(entry.getArchive().getArchivePath().toString());
mainWindow.getCheckButton().setDisable(false);
mainWindow.getLod1Btn().setDisable(false);
mainWindow.getLod2Btn().setDisable(false);
mainWindow.getLod3Btn().setDisable(false);
mainWindow.getLod4Btn().setDisable(false);
mainWindow.getWorldBtn().setDisable(false);
mainWindow.getSaveBtn().setDisable(false);
mainWindow.getResetCameraBtn().setDisable(false);
mainWindow.getHideRoofBtn().setDisable(false);
mainWindow.getZipManagerBtn().setDisable(false);
mainWindow.getNorthArrow().setVisible(true); mainWindow.getNorthArrow().setVisible(true);
mainWindow.alignNorthArrow(); mainWindow.alignNorthArrow();
setupFeatureTabs(); setupFeatureTabs();
buildTrees(); buildTrees();
updateFeatureTrees();
mainWindow.getWriteReportButton().setDisable(currentChecker == null);
}); });
} finally { } finally {
Platform.runLater(() -> mainWindow.getOpenBtn().setDisable(false)); Platform.runLater(() -> mainWindow.getOpenBtn().setDisable(false));
} }
} }
public void showZipManager() { public static int getMaxFeaturesPerChunk(){
Platform.runLater(() -> currentZipEntryManager.show()); return MAX_FEATURES_PER_CHUNK;
} }
private void setupFeatureTabs() { private void setupFeatureTabs() {
mainWindow.setDisableOfFeatureTab(FeatureType.BUILDING, model.getBuildings().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.BUILDING, model.getBuildingCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.VEGETATION, model.getVegetation().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.VEGETATION, model.getVegetationCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.TRANSPORTATION, model.getTransportation().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.TRANSPORTATION, model.getTransportationCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.TUNNEL, model.getTunnels().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.TUNNEL, model.getTunnelCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.BRIDGE, model.getBridges().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.BRIDGE, model.getBridgeCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.WATER, model.getWater().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.WATER, model.getWaterCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.LAND, model.getLand().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.LAND, model.getLandCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.CITY_FURNITURE, model.getCityFurniture().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.CITY_FURNITURE, model.getCityFurnitureCount() == 0);
mainWindow.setDisableOfFeatureTab(FeatureType.GENERIC_CITY_OBJECT, model.getGenericCityObjects().isEmpty()); mainWindow.setDisableOfFeatureTab(FeatureType.OTHER_CITY_OBJECT, model.getOtherCityObjectsCount() == 0);
} }
public void buildTrees() { public void buildTrees() {
...@@ -281,7 +178,7 @@ public class CityDoctorController { ...@@ -281,7 +178,7 @@ public class CityDoctorController {
buildWater(model); buildWater(model);
buildLand(model); buildLand(model);
buildCityFurniture(model); buildCityFurniture(model);
buildOtherCityObjects(model); buildGenericCityObjects(model);
buildTunnel(model); buildTunnel(model);
} }
...@@ -294,126 +191,134 @@ public class CityDoctorController { ...@@ -294,126 +191,134 @@ public class CityDoctorController {
waterChunkNr.set(0); waterChunkNr.set(0);
landChunkNr.set(0); landChunkNr.set(0);
cityFurnitureChunkNr.set(0); cityFurnitureChunkNr.set(0);
genericCityObjectsChunkNr.set(0); otherCityObjectsChunkNr.set(0);
} }
private void buildLand(CityDoctorModel model) { private void buildLand(CityDoctorModel model) {
if (model.getLand().isEmpty()) { if (model.getLandCount() == 0) {
return; return;
} }
TreeView<Renderable> landView = mainWindow.getTerrainView(); TreeView<Renderable> landView = mainWindow.getTerrainView();
TreeItem<Renderable> landRoot = new TreeItem<>(new CityObjectGroupNode(model.getLand(), "Land", TreeItem<Renderable> landRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Land",
Color.BROWN)); Color.BROWN));
landRoot.setExpanded(true); landRoot.setExpanded(true);
landView.setRoot(landRoot); landView.setRoot(landRoot);
buildLandFromList(model.getLand(), landView.getRoot()); Supplier<Stream<CityObject>> supply = model::getLand;
addMoreButtonIfNecessary(model.getLand(), landView, landRoot, landChunkNr); buildLandTreeFromList(supply, landView.getRoot());
addMoreButtonForLand(landView, landRoot, landChunkNr, supply, model.getLandCount());
} }
private void buildLandFromList(List<CityObject> list, TreeItem<Renderable> root) { private void buildLandTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root) {
int landChunk = landChunkNr.get(); int landChunk = landChunkNr.get();
for (int i = landChunk * MAX_FEATURES_PER_CHUNK; i < (landChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) landChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(land ->{
&& i < list.size(); i++) {
CityObject land = list.get(i);
CityObjectNode node = new CityObjectNode(land); CityObjectNode node = new CityObjectNode(land);
TreeItem<Renderable> item = new TreeItem<>(node); TreeItem<Renderable> item = new TreeItem<>(node);
item.setExpanded(true); item.setExpanded(true);
root.getChildren().add(item); root.getChildren().add(item);
createGeometryNodes(land, item); createGeometryNodes(land, item);
});
}
} }
private void buildCityFurniture(CityDoctorModel model) { private void buildCityFurniture(CityDoctorModel model) {
if (model.getCityFurniture().isEmpty()) { if (model.getCityFurnitureCount() == 0) {
return; return;
} }
TreeView<Renderable> cityFurnitureView = mainWindow.getCityFurnitureView(); TreeView<Renderable> cityFurnitureView = mainWindow.getCityFurnitureView();
TreeItem<Renderable> cityFurnitureRoot = new TreeItem<>(new CityObjectGroupNode(model.getCityFurniture(), TreeItem<Renderable> cityFurnitureRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(),
"City Furniture", Color.BLUEVIOLET)); "City Furniture", Color.BLUEVIOLET));
cityFurnitureRoot.setExpanded(true); cityFurnitureRoot.setExpanded(true);
cityFurnitureView.setRoot(cityFurnitureRoot); cityFurnitureView.setRoot(cityFurnitureRoot);
buildCityFurnitureTreeFromList(model.getCityFurniture(), cityFurnitureView.getRoot()); Supplier<Stream<CityFurniture>> supply = model::getCityFurniture;
addMoreButtonIfNecessary(model.getCityFurniture(), cityFurnitureView, cityFurnitureRoot, cityFurnitureChunkNr); buildCityFurnitureTreeFromList(supply, cityFurnitureView.getRoot());
addMoreButtonForCityFurniture(cityFurnitureView, cityFurnitureRoot, cityFurnitureChunkNr, supply,
model.getCityFurnitureCount());
} }
private void buildOtherCityObjects(CityDoctorModel model) { private void buildGenericCityObjects(CityDoctorModel model) {
if (model.getGenericCityObjects().isEmpty()) { if (model.getOtherCityObjectsCount() == 0) {
return; return;
} }
TreeView<Renderable> otherObjectsView = mainWindow.getGenericCityObjectView(); TreeView<Renderable> otherObjectsView = mainWindow.getOtherCityObjectView();
TreeItem<Renderable> otherObjectsRoot = new TreeItem<>(new CityObjectGroupNode(model.getGenericCityObjects(), TreeItem<Renderable> otherObjectsRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(),
"Generic CityObjects", Color.DARKGRAY)); "Generic CityObjects", Color.DARKGRAY));
otherObjectsRoot.setExpanded(true); otherObjectsRoot.setExpanded(true);
otherObjectsView.setRoot(otherObjectsRoot); otherObjectsView.setRoot(otherObjectsRoot);
buildGenericCityObjectTreeFromList(model.getGenericCityObjects(), otherObjectsView.getRoot()); Supplier<Stream<CityObject>> supply = model::getOtherCityObjects;
addMoreButtonIfNecessary(model.getGenericCityObjects(), otherObjectsView, otherObjectsRoot, genericCityObjectsChunkNr); buildOtherCityObjectsTreeFromList(supply, otherObjectsView.getRoot());
addMoreButtonForOtherCityObjects( otherObjectsView, otherObjectsRoot, otherCityObjectsChunkNr, supply,
model.getOtherCityObjectsCount());
} }
private void buildWater(CityDoctorModel model) { private void buildWater(CityDoctorModel model) {
if (model.getWater().isEmpty()) { if (model.getWaterCount() == 0) {
return; return;
} }
TreeView<Renderable> waterView = mainWindow.getWaterView(); TreeView<Renderable> waterView = mainWindow.getWaterView();
TreeItem<Renderable> waterRoot = new TreeItem<>(new CityObjectGroupNode(model.getWater(), "Water", TreeItem<Renderable> waterRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Water",
Color.LIGHTSKYBLUE)); Color.LIGHTSKYBLUE));
waterRoot.setExpanded(true); waterRoot.setExpanded(true);
waterView.setRoot(waterRoot); waterView.setRoot(waterRoot);
buildWaterTreeFromList(model.getWater(), waterRoot); Supplier<Stream<WaterObject>> supply = model::getWater;
addMoreButtonIfNecessary(model.getWater(), waterView, waterRoot, waterChunkNr); buildWaterTreeFromList(supply, waterRoot);
addMoreButtonForWater(waterView, waterRoot, waterChunkNr, supply, model.getWaterCount());
} }
private void buildBridges(CityDoctorModel model) { private void buildBridges(CityDoctorModel model) {
if (model.getBridges().isEmpty()) { if (model.getBridgeCount() == 0) {
return; return;
} }
TreeView<Renderable> bridgeView = mainWindow.getBridgeView(); TreeView<Renderable> bridgeView = mainWindow.getBridgeView();
TreeItem<Renderable> bridgeRoot = new TreeItem<>(new CityObjectGroupNode(model.getBridges(), "Bridges", TreeItem<Renderable> bridgeRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Bridges",
Color.CORAL)); Color.CORAL));
bridgeRoot.setExpanded(true); bridgeRoot.setExpanded(true);
bridgeView.setRoot(bridgeRoot); bridgeView.setRoot(bridgeRoot);
buildBridgeTreeFromList(model.getBridges(), bridgeView.getRoot()); Supplier<Stream<BridgeObject>> supply = model::getBridges;
addMoreButtonIfNecessary(model.getBridges(), bridgeView, bridgeRoot, bridgeChunkNr); buildBridgeTreeFromList(supply, bridgeView.getRoot());
addMoreButtonForBridges(bridgeView, bridgeRoot, bridgeChunkNr, supply, model.getBridgeCount());
} }
private void buildTransportation(CityDoctorModel model) { private void buildTransportation(CityDoctorModel model) {
if (model.getTransportation().isEmpty()) { if (model.getTransportationCount() == 0) {
return; return;
} }
TreeView<Renderable> transView = mainWindow.getTransportationView(); TreeView<Renderable> transView = mainWindow.getTransportationView();
TreeItem<Renderable> transRoot = new TreeItem<>(new CityObjectGroupNode(model.getTransportation(), TreeItem<Renderable> transRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(),
"Transportation", Color.YELLOW)); "Transportation", Color.YELLOW));
transRoot.setExpanded(true); transRoot.setExpanded(true);
transView.setRoot(transRoot); transView.setRoot(transRoot);
buildTransportationTreeFromList(model.getTransportation(), transView.getRoot()); Supplier<Stream<TransportationObject>> supply = model::getTransportation;
addMoreButtonIfNecessary(model.getTransportation(), transView, transRoot, transportationChunkNr); buildTransportationTreeFromList(supply, transView.getRoot());
addMoreButtonForTransportation(transView, transRoot, transportationChunkNr, supply,
model.getTransportationCount());
} }
private void buildTunnel(CityDoctorModel model) { private void buildTunnel(CityDoctorModel model) {
if (model.getTunnels().isEmpty()) { if (model.getTunnelCount() == 0) {
return; return;
} }
TreeView<Renderable> tunnelView = mainWindow.getTunnelView(); TreeView<Renderable> tunnelView = mainWindow.getTunnelView();
TreeItem<Renderable> tunnelRoot = new TreeItem<>(new CityObjectGroupNode(model.getTunnels(), "Tunnel", TreeItem<Renderable> tunnelRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Tunnel",
Color.SLATEGRAY)); Color.SLATEGRAY));
tunnelRoot.setExpanded(true); tunnelRoot.setExpanded(true);
tunnelView.setRoot(tunnelRoot); tunnelView.setRoot(tunnelRoot);
buildTunnelTreeFromList(model.getTunnels(), tunnelRoot); Supplier<Stream<Tunnel>> supply = model::getTunnels;
addMoreButtonIfNecessary(model.getTunnels(), tunnelView, tunnelRoot, tunnelChunkNr); buildTunnelTreeFromList(supply, tunnelRoot);
addMoreButtonForTunnel(tunnelView, tunnelRoot, tunnelChunkNr, supply, model.getTunnelCount());
} }
private void buildVegetation(CityDoctorModel model) { private void buildVegetation(CityDoctorModel model) {
if (model.getVegetation().isEmpty()) { if (model.getVegetationCount() == 0) {
return; return;
} }
TreeView<Renderable> vegetationsView = mainWindow.getVegetationView(); TreeView<Renderable> vegetationsView = mainWindow.getVegetationView();
TreeItem<Renderable> vegRoot = new TreeItem<>(new CityObjectGroupNode(model.getVegetation(), TreeItem<Renderable> vegRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(),
"Vegetation", Color.LIGHTGREEN)); "Vegetation", Color.LIGHTGREEN));
vegRoot.setExpanded(true); vegRoot.setExpanded(true);
vegetationsView.setRoot(vegRoot); vegetationsView.setRoot(vegRoot);
buildVegetationTreeFromList(model.getVegetation(), vegRoot); Supplier<Stream<Vegetation>> supply = model::getVegetation;
addMoreButtonIfNecessary(model.getVegetation(), vegetationsView, vegRoot, vegetationChunkNr); buildVegetationTreeFromList(supply, vegRoot);
addMoreButtonForVegetation(vegetationsView, vegRoot, vegetationChunkNr, supply, model.getVegetationCount());
} }
private void addMoreButtonIfNecessary(List<? extends CityObject> list, TreeView<Renderable> view, private void addMoreButtonIfNecessary(List<? extends CityObject> list, TreeView<Renderable> view,
...@@ -429,7 +334,7 @@ public class CityDoctorController { ...@@ -429,7 +334,7 @@ public class CityDoctorController {
chunkCounter.incrementAndGet(); chunkCounter.incrementAndGet();
int visibleFeatures = countVisibleNodes(view); int visibleFeatures = countVisibleNodes(view);
buildTreeFromList(list, root, chunkCounter); // buildTreeFromList(list, root, chunkCounter);
updateTree(root); updateTree(root);
if (selectedIndex >= 0) { if (selectedIndex >= 0) {
view.getSelectionModel().select(selectedIndex); view.getSelectionModel().select(selectedIndex);
...@@ -445,17 +350,34 @@ public class CityDoctorController { ...@@ -445,17 +350,34 @@ public class CityDoctorController {
} }
} }
private void moreButton(CityDoctorModel model, TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<CityObject>> streamSupplier){
int featureCount = model.getBuildingCount();
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildTreeFromList(streamSupplier, root, chunkCounter);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void buildBuildings(CityDoctorModel model) { private void buildBuildings(CityDoctorModel model) {
if (model.getBuildings().isEmpty()) { if (model.getBuildingCount() == 0) {
return; return;
} }
TreeView<Renderable> buildingsView = mainWindow.getBuildingsView(); TreeView<Renderable> buildingsView = mainWindow.getBuildingsView();
TreeItem<Renderable> root = new TreeItem<>(new CityObjectGroupNode(model.getBuildings(), "Buildings", TreeItem<Renderable> root = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Buildings",
Color.WHITE)); Color.WHITE));
root.setExpanded(true); root.setExpanded(true);
buildingsView.setRoot(root); buildingsView.setRoot(root);
buildBuildingTreeFromList(model.getBuildings(), root); Supplier<Stream<Building>> supply = model::getBuildings;
addMoreButtonToBuildingsIfNecessary(model.getBuildings(), buildingsView, root, buildingChunkNr); buildBuildingTreeFromList(supply, root);
addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, supply, model.getBuildingCount());
} }
...@@ -471,7 +393,7 @@ public class CityDoctorController { ...@@ -471,7 +393,7 @@ public class CityDoctorController {
root.getChildren().remove(root.getChildren().size() - 1); root.getChildren().remove(root.getChildren().size() - 1);
chunkCounter.getAndIncrement(); chunkCounter.getAndIncrement();
int visibleFeatures = countVisibleNodes(view); int visibleFeatures = countVisibleNodes(view);
buildBuildingTreeFromList(list, root); // buildBuildingTreeFromList(list, root);
updateTree(root); updateTree(root);
if (selectedIndex >= 0) { if (selectedIndex >= 0) {
view.getSelectionModel().select(selectedIndex); view.getSelectionModel().select(selectedIndex);
...@@ -487,6 +409,141 @@ public class CityDoctorController { ...@@ -487,6 +409,141 @@ public class CityDoctorController {
} }
} }
private void addMoreButtonForBuildings(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<Building>> supply, int featureCount) {
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildBuildingTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForBridges(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<BridgeObject>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildBridgeTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForVegetation(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<Vegetation>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildVegetationTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForTunnel(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<Tunnel>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildTunnelTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForTransportation(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<TransportationObject>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildTransportationTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForLand(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<CityObject>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildLandTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForWater(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<WaterObject>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildWaterTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForCityFurniture(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<CityFurniture>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildCityFurnitureTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private void addMoreButtonForOtherCityObjects(TreeView<Renderable> view, TreeItem<Renderable> root,
AtomicInteger chunkCounter, Supplier<Stream<CityObject>> supply, int featureCount){
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
AddMoreButtonRunnable run = new AddMoreButtonRunnable(featureCount, view, root, chunkCounter) {
@Override
public void buildNodeTreeCall() {
buildOtherCityObjectsTreeFromList(supply, root);
updateTree(root);
}
};
//add button
root.getChildren().add(new TreeItem<>(new ButtonRenderable(run)));
}
}
private static int countVisibleNodes(TreeView<Renderable> view) { private static int countVisibleNodes(TreeView<Renderable> view) {
return countVisibleNodes(view.getRoot()) + 1; return countVisibleNodes(view.getRoot()) + 1;
} }
...@@ -501,17 +558,16 @@ public class CityDoctorController { ...@@ -501,17 +558,16 @@ public class CityDoctorController {
return visibleFeatures; return visibleFeatures;
} }
private void buildTreeFromList(List<? extends CityObject> cos, TreeItem<Renderable> root, private void buildTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root,
AtomicInteger chunkCounter) { AtomicInteger chunkCounter) {
int chunk = chunkCounter.get(); int buildingChunk = buildingChunkNr.get();
for (int i = chunk * MAX_FEATURES_PER_CHUNK; i < (chunk + 1) * MAX_FEATURES_PER_CHUNK && i < cos.size(); i++) { supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(co ->{
CityObject co = cos.get(i);
CityObjectNode node = new CityObjectNode(co); CityObjectNode node = new CityObjectNode(co);
TreeItem<Renderable> nodeItem = new TreeItem<>(node); TreeItem<Renderable> nodeItem = new TreeItem<>(node);
nodeItem.setExpanded(true); nodeItem.setExpanded(true);
root.getChildren().add(nodeItem); root.getChildren().add(nodeItem);
createGeometryNodes(co, nodeItem); createGeometryNodes(co, nodeItem);
} });
} }
private <T extends CityObject> void buildTreeFromListWithProducer(List<T> cos, TreeItem<Renderable> root, private <T extends CityObject> void buildTreeFromListWithProducer(List<T> cos, TreeItem<Renderable> root,
...@@ -535,7 +591,7 @@ public class CityDoctorController { ...@@ -535,7 +591,7 @@ public class CityDoctorController {
mainWindow.getWaterView().setRoot(null); mainWindow.getWaterView().setRoot(null);
mainWindow.getTerrainView().setRoot(null); mainWindow.getTerrainView().setRoot(null);
mainWindow.getCityFurnitureView().setRoot(null); mainWindow.getCityFurnitureView().setRoot(null);
mainWindow.getGenericCityObjectView().setRoot(null); mainWindow.getOtherCityObjectView().setRoot(null);
mainWindow.getErrorTree().getRoot().getChildren().clear(); mainWindow.getErrorTree().getRoot().getChildren().clear();
mainWindow.getAttributeView().getRoot().getChildren().clear(); mainWindow.getAttributeView().getRoot().getChildren().clear();
mainWindow.getGlobalErrorsView().getItems().clear(); mainWindow.getGlobalErrorsView().getItems().clear();
...@@ -582,11 +638,9 @@ public class CityDoctorController { ...@@ -582,11 +638,9 @@ public class CityDoctorController {
return nodeItem; return nodeItem;
} }
private void buildBuildingTreeFromList(List<Building> list, TreeItem<Renderable> root) { private void buildBuildingTreeFromList(Supplier<Stream<Building>> supply, TreeItem<Renderable> root) {
int buildingChunk = buildingChunkNr.get(); int buildingChunk = buildingChunkNr.get();
for (int i = buildingChunk * MAX_FEATURES_PER_CHUNK; i < (buildingChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(b ->{
&& i < list.size(); i++) {
Building b = list.get(i);
TreeItem<Renderable> item = buildTopLevelCityObjectNode(b, root, b.getBoundarySurfaces()); TreeItem<Renderable> item = buildTopLevelCityObjectNode(b, root, b.getBoundarySurfaces());
createBuildingInstallationNodes(b, item); createBuildingInstallationNodes(b, item);
...@@ -596,14 +650,12 @@ public class CityDoctorController { ...@@ -596,14 +650,12 @@ public class CityDoctorController {
createBuildingStoreyNodes(b, item); createBuildingStoreyNodes(b, item);
createBuildingUnitNodes(b, item); createBuildingUnitNodes(b, item);
createBuildingPartNodes(b, item); createBuildingPartNodes(b, item);
} });
} }
private void buildBridgeTreeFromList(List<BridgeObject> list, TreeItem<Renderable> root) { private void buildBridgeTreeFromList(Supplier<Stream<BridgeObject>> supply, TreeItem<Renderable> root) {
int bridgeChunk = bridgeChunkNr.get(); int bridgeChunk = bridgeChunkNr.get();
for (int i = bridgeChunk * MAX_FEATURES_PER_CHUNK; i < (bridgeChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) bridgeChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(bridge ->{
&& i < list.size(); i++) {
BridgeObject bridge = list.get(i);
TreeItem<Renderable> item = buildTopLevelCityObjectNode(bridge, root, bridge.getBoundarySurfaces()); TreeItem<Renderable> item = buildTopLevelCityObjectNode(bridge, root, bridge.getBoundarySurfaces());
createBridgeRoomNodes(bridge, item); createBridgeRoomNodes(bridge, item);
...@@ -611,55 +663,46 @@ public class CityDoctorController { ...@@ -611,55 +663,46 @@ public class CityDoctorController {
createBridgeFurnitureNodes(bridge, item); createBridgeFurnitureNodes(bridge, item);
createBridgeConstructiveElementsNodes(bridge, item); createBridgeConstructiveElementsNodes(bridge, item);
createBridgePartNodes(bridge, item); createBridgePartNodes(bridge, item);
} });
} }
private void buildTransportationTreeFromList(List<TransportationObject> list, TreeItem<Renderable> root) { private void buildTransportationTreeFromList(Supplier<Stream<TransportationObject>> supply, TreeItem<Renderable> root) {
int transportChunk = transportationChunkNr.get(); int transportChunk = transportationChunkNr.get();
for (int i = transportChunk * MAX_FEATURES_PER_CHUNK; i < (transportChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) transportChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(trans ->{
&& i < list.size(); i++) { TreeItem<Renderable> item = buildTopLevelCityObjectNode(trans, root);
TransportationObject t = list.get(i); createTransportSectionNodes(trans, item);
TreeItem<Renderable> item = buildTopLevelCityObjectNode(t, root); createTrafficSpacesNodes(trans, item);
createTransportSectionNodes(t, item); });
createTrafficSpacesNodes(t, item);
}
} }
private void buildVegetationTreeFromList(List<Vegetation> list, TreeItem<Renderable> root) { private void buildVegetationTreeFromList(Supplier<Stream<Vegetation>> supply, TreeItem<Renderable> root) {
int vegetationChunk = vegetationChunkNr.get(); int vegetationChunk = vegetationChunkNr.get();
for (int i = vegetationChunk * MAX_FEATURES_PER_CHUNK; i < (vegetationChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) vegetationChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(veg ->{
&& i < list.size(); i++) { buildTopLevelCityObjectNode(veg, root);
Vegetation v = list.get(i); });
buildTopLevelCityObjectNode(v, root);
}
} }
private void buildWaterTreeFromList(List<WaterObject> list, TreeItem<Renderable> root) { private void buildWaterTreeFromList(Supplier<Stream<WaterObject>> supply, TreeItem<Renderable> root) {
int waterChunk = waterChunkNr.get(); int waterChunk = waterChunkNr.get();
for (int i = waterChunk * MAX_FEATURES_PER_CHUNK; i < (waterChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) waterChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(wat ->{
&& i < list.size(); i++) { buildTopLevelCityObjectNode(wat, root);
WaterObject w = list.get(i); });
buildTopLevelCityObjectNode(w, root);
}
} }
private void buildCityFurnitureTreeFromList(List<CityFurniture> list, TreeItem<Renderable> root) { private void buildCityFurnitureTreeFromList(Supplier<Stream<CityFurniture>> supply, TreeItem<Renderable> root) {
int cityFurnChunk = cityFurnitureChunkNr.get(); int cityFurnChunk = cityFurnitureChunkNr.get();
for (int i = cityFurnChunk * MAX_FEATURES_PER_CHUNK; i < (cityFurnChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) cityFurnChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(cf ->{
&& i < list.size(); i++) {
CityFurniture cf = list.get(i);
buildTopLevelCityObjectNode(cf, root); buildTopLevelCityObjectNode(cf, root);
} });
} }
private void buildGenericCityObjectTreeFromList(List<GenericCityObject> list, TreeItem<Renderable> root) { private void buildOtherCityObjectsTreeFromList(Supplier<Stream<CityObject>> supply, TreeItem<Renderable> root) {
int genericObjectChunk = genericCityObjectsChunkNr.get(); int genericObjectChunk = otherCityObjectsChunkNr.get();
for (int i = genericObjectChunk * MAX_FEATURES_PER_CHUNK; i < (genericObjectChunk + 1) * MAX_FEATURES_PER_CHUNK supply.get().skip((long) genericObjectChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(gen ->{
&& i < list.size(); i++) { buildTopLevelCityObjectNode(gen, root);
GenericCityObject goc = list.get(i); });
buildTopLevelCityObjectNode(goc, root);
}
} }
private void createTransportSectionNodes(TransportationObject t, TreeItem<Renderable> root) { private void createTransportSectionNodes(TransportationObject t, TreeItem<Renderable> root) {
...@@ -733,10 +776,9 @@ public class CityDoctorController { ...@@ -733,10 +776,9 @@ public class CityDoctorController {
} }
private void buildTunnelTreeFromList(List<Tunnel> list, TreeItem<Renderable> root) { private void buildTunnelTreeFromList(Supplier<Stream<Tunnel>> supply, TreeItem<Renderable> root) {
int tunnelChunk = tunnelChunkNr.get(); int tunnelChunk = tunnelChunkNr.get();
for (int i = tunnelChunk * MAX_FEATURES_PER_CHUNK; i < (tunnelChunk + 1) * MAX_FEATURES_PER_CHUNK && i < list.size(); i++) { supply.get().skip((long) tunnelChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(tunnel ->{
Tunnel tunnel = list.get(i);
TreeItem<Renderable> item = buildTopLevelCityObjectNode(tunnel, root); TreeItem<Renderable> item = buildTopLevelCityObjectNode(tunnel, root);
createTunnelHollowNodes(tunnel, item); createTunnelHollowNodes(tunnel, item);
...@@ -744,7 +786,8 @@ public class CityDoctorController { ...@@ -744,7 +786,8 @@ public class CityDoctorController {
createTunnelFurnitureNodes(tunnel, item); createTunnelFurnitureNodes(tunnel, item);
createTunnelConstructiveElementsNodes(tunnel, item); createTunnelConstructiveElementsNodes(tunnel, item);
createTunnelPartNodes(tunnel, item); createTunnelPartNodes(tunnel, item);
} });
} }
private void createTunnelInstallationNodes(Tunnel tunnel, TreeItem<Renderable> root) { private void createTunnelInstallationNodes(Tunnel tunnel, TreeItem<Renderable> root) {
...@@ -1035,20 +1078,14 @@ public class CityDoctorController { ...@@ -1035,20 +1078,14 @@ public class CityDoctorController {
config.setNumberOfRoundingPlacesInGlobalParameters(currentConfig.getNumberOfRoundingPlaces()); config.setNumberOfRoundingPlacesInGlobalParameters(currentConfig.getNumberOfRoundingPlaces());
config.setParserConfig(currentConfig); config.setParserConfig(currentConfig);
currentChecker = new Checker(config, model); currentChecker = new Checker(config, model);
if (previousCheckers != null) {
previousCheckers.put(model, currentChecker);
}
currentChecker.runChecks(l); currentChecker.runChecks(l);
Platform.runLater(() -> { Platform.runLater(() -> {
// apply check results to tree views // apply check results to tree views
buildTrees();
updateFeatureTrees(); updateFeatureTrees();
updateTree(mainWindow.getPolygonsView().getRoot()); updateTree(mainWindow.getPolygonsView().getRoot());
for (CheckError e : model.getGlobalErrors()) { updateGlobalErrors();
if (e instanceof SchematronError se) {
mainWindow.getGlobalErrorsView().getItems().add(se.getErrorIdString() + " - " + se.getNameOfAttribute());
}
}
renderer.refresh(); renderer.refresh();
mainWindow.getWriteReportButton().setDisable(false); mainWindow.getWriteReportButton().setDisable(false);
}); });
...@@ -1057,134 +1094,10 @@ public class CityDoctorController { ...@@ -1057,134 +1094,10 @@ public class CityDoctorController {
} }
} }
public void startZipFileChecks(ValidationConfiguration config, ProgressListener l, boolean lowMemoryMode, private void updateGlobalErrors() {
Path outputPath, boolean pdfReports, boolean xmlReports) { GlobalErrorVisitor globErrVisitor = new GlobalErrorVisitor(mainWindow);
if (zipArchive == null && logger.isWarnEnabled()) { for (CheckError e : model.getGlobalErrors()) {
logger.warn(Localization.getText("CityDoctorController.noZipFile")); e.accept(globErrVisitor);
}
if (lowMemoryMode) {
startZipFileCheckStream(config, outputPath, pdfReports, xmlReports);
return;
}
try {
Platform.runLater(() -> {
mainWindow.getCheckButton().setDisable(true);
mainWindow.getErrorTree().getRoot().getChildren().clear();
mainWindow.getGlobalErrorsView().getItems().clear();
});
previousCheckers = new HashMap<>();
zipArchive.mountArchive(currentConfig);
config.setNumberOfRoundingPlacesInGlobalParameters(currentConfig.getNumberOfRoundingPlaces());
config.setParserConfig(currentConfig);
int totalEntries = zipArchive.getEntries().size();
int checkedEntries = 0;
for (CityGmlZipEntry entry : zipArchive.getEntries()) {
if (entry.getErrorType() != null && entry.getModel() == null) {
continue;
}
model = entry.getModel();
currentChecker = new Checker(config, model);
currentChecker.runChecks();
previousCheckers.put(model, currentChecker);
checkedEntries++;
if (l != null) {
l.updateProgress((float) checkedEntries / totalEntries);
}
}
Platform.runLater(() -> {
// apply check results to tree views
updateFeatureTrees();
updateTree(mainWindow.getPolygonsView().getRoot());
for (CheckError e : model.getGlobalErrors()) {
if (e instanceof SchematronError se) {
mainWindow.getGlobalErrorsView().getItems().add(se.getErrorIdString() + " - " + se.getNameOfAttribute());
}
}
renderer.refresh();
mainWindow.getWriteReportButton().setDisable(false);
currentZipEntryManager.refresh();
});
} finally {
Platform.runLater(() -> mainWindow.getCheckButton().setDisable(false));
}
}
private void startZipFileCheckStream(ValidationConfiguration valConfig, Path outputPath, boolean pdfReports,
boolean xmlReports) {
try {
Path outputZipDirectory = null;
if (outputPath.toFile().isDirectory()) {
String filename = FilenameUtils.removeExtension(zipArchive.getArchivePath().getFileName().toString());
filename = filename + "_validated";
outputZipDirectory = outputPath.resolve(filename);
Files.createDirectories(outputZipDirectory);
} else {
String filename = FilenameUtils.removeExtension(outputPath.toAbsolutePath().getFileName().toString());
outputZipDirectory = Path.of(filename);
}
String xmlReportsDirectory = null;
String pdfReportsDirectory = null;
if (xmlReports) {
xmlReportsDirectory = Files.createDirectories(
outputZipDirectory.resolve("xml_reports/")).toAbsolutePath().toString();
}
if (pdfReports) {
pdfReportsDirectory = Files.createDirectories(
outputZipDirectory.resolve("pdf_reports/")).toAbsolutePath().toString();
}
Checker.streamCheck(zipArchive, xmlReportsDirectory, pdfReportsDirectory, valConfig, outputZipDirectory.toString());
Desktop desktop = Desktop.getDesktop();
desktop.open(outputPath.toFile());
} catch (CityGmlParseException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void saveZipArchiveReports(File outputZipDirectory) {
if (zipArchive == null) {
return;
}
String directoryName = FilenameUtils.removeExtension(outputZipDirectory.getAbsolutePath());
Path tempOutput = Path.of(directoryName + File.separator);
File temp = null;
try {
temp = tempOutput.toFile();
for (CityGmlZipEntry entry : zipArchive.getEntries()) {
if (entry.getErrorType() != null || entry.getModel() == null) {
continue;
}
model = entry.getModel();
if (model.isValidated()) {
Checker checker = previousCheckers.get(model);
Files.createDirectories(tempOutput.resolve(entry.getEntrySubPath()).getParent());
checker.writeXmlReport(tempOutput.resolve(entry.getDisplayName() + "_report.xml").toString());
checker.writePdfReport(tempOutput.resolve(entry.getDisplayName() + "_report.pdf").toString());
}
}
ArchivePacker.packAndDeleteDirectory(tempOutput.toString());
temp = null;
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Export Report");
alert.setContentText(Localization.getText("CityDoctorController.saveZipArchiveReports"));
alert.showAndWait();
} catch (IOException e) {
logger.error(e);
} finally {
try {
if (temp != null) {
FileUtils.deleteDirectory(temp);
}
} catch (IOException e) {
logger.error(e);
}
} }
} }
...@@ -1196,7 +1109,7 @@ public class CityDoctorController { ...@@ -1196,7 +1109,7 @@ public class CityDoctorController {
updateTree(mainWindow.getCityFurnitureView().getRoot()); updateTree(mainWindow.getCityFurnitureView().getRoot());
updateTree(mainWindow.getTransportationView().getRoot()); updateTree(mainWindow.getTransportationView().getRoot());
updateTree(mainWindow.getWaterView().getRoot()); updateTree(mainWindow.getWaterView().getRoot());
updateTree(mainWindow.getGenericCityObjectView().getRoot()); updateTree(mainWindow.getOtherCityObjectView().getRoot());
updateTree(mainWindow.getTunnelView().getRoot()); updateTree(mainWindow.getTunnelView().getRoot());
renderer.updateErrors(); renderer.updateErrors();
} }
...@@ -1236,15 +1149,13 @@ public class CityDoctorController { ...@@ -1236,15 +1149,13 @@ public class CityDoctorController {
private Map<ErrorId, ErrorStat> getErrorStats() { private Map<ErrorId, ErrorStat> getErrorStats() {
Map<ErrorId, ErrorStat> stats = new HashMap<>(); Map<ErrorId, ErrorStat> stats = new HashMap<>();
addErrorStats(stats, model.getBridges()); List<CheckError> errors = new ArrayList<>();
addErrorStats(stats, model.getBuildings()); model.createFeatureStream().forEach(co -> co.collectContainedErrors(errors));
addErrorStats(stats, model.getLand()); Set<CheckError> filteredErrors = new HashSet<>(errors);
addErrorStats(stats, model.getTunnels()); for (CheckError error : filteredErrors) {
addErrorStats(stats, model.getTransportation()); ErrorStat stat = stats.computeIfAbsent(error.getErrorId(), ErrorStat::new);
addErrorStats(stats, model.getVegetation()); stat.incrementCount();
addErrorStats(stats, model.getWater()); }
addErrorStats(stats, model.getCityFurniture());
addErrorStats(stats, model.getGenericCityObjects());
return stats; return stats;
} }
...@@ -1258,13 +1169,15 @@ public class CityDoctorController { ...@@ -1258,13 +1169,15 @@ public class CityDoctorController {
ErrorStat stat = stats.computeIfAbsent(error.getErrorId(), ErrorStat::new); ErrorStat stat = stats.computeIfAbsent(error.getErrorId(), ErrorStat::new);
stat.incrementCount(); stat.incrementCount();
} }
} }
public void export(CityObject co) { public void export(CityObject co) {
if (model == null) { if (model == null) {
return; return;
} }
CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile()); CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile(), new UnconnectedCache());
newModel.setCityModel(new CityModel()); newModel.setCityModel(new CityModel());
newModel.addCityObject(co); newModel.addCityObject(co);
newModel.setParsedCityGMLVersion(model.getCityGMLVersion()); newModel.setParsedCityGMLVersion(model.getCityGMLVersion());
...@@ -1319,96 +1232,113 @@ public class CityDoctorController { ...@@ -1319,96 +1232,113 @@ public class CityDoctorController {
case WATER -> filterWaterTree(searchString); case WATER -> filterWaterTree(searchString);
case LAND -> filterLandTree(searchString); case LAND -> filterLandTree(searchString);
case CITY_FURNITURE -> filterCityFurnitureTree(searchString); case CITY_FURNITURE -> filterCityFurnitureTree(searchString);
case GENERIC_CITY_OBJECT -> filterGenericCityObjectTree(searchString); case OTHER_CITY_OBJECT -> filterOtherCityObjectsTree(searchString);
} }
} }
private void filterBuildingTree(String searchString) { private void filterBuildingTree(String searchString) {
List<Building> foundBuildings = filterFeatures(searchString, model.getBuildings()); Supplier<Stream<Building>> foundBuildings = () -> model.getBuildings().
filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundBuildings.get().count();
TreeView<Renderable> buildingsView = mainWindow.getBuildingsView(); TreeView<Renderable> buildingsView = mainWindow.getBuildingsView();
TreeItem<Renderable> root = buildingsView.getRoot(); TreeItem<Renderable> root = buildingsView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildBuildingTreeFromList(foundBuildings, root); buildBuildingTreeFromList(foundBuildings, root);
updateTree(root); updateTree(root);
addMoreButtonToBuildingsIfNecessary(foundBuildings, buildingsView, root, buildingChunkNr); addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, foundBuildings, featureCount);
} }
private void filterBridgeTree(String searchString) { private void filterBridgeTree(String searchString) {
List<BridgeObject> foundBridges = filterFeatures(searchString, model.getBridges()); Supplier<Stream<BridgeObject>> foundBridges = () -> model.getBridges().
filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundBridges.get().count();
TreeView<Renderable> bridgeView = mainWindow.getBridgeView(); TreeView<Renderable> bridgeView = mainWindow.getBridgeView();
TreeItem<Renderable> root = bridgeView.getRoot(); TreeItem<Renderable> root = bridgeView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildBridgeTreeFromList(foundBridges, root); buildBridgeTreeFromList(foundBridges, root);
updateTree(root); updateTree(root);
addMoreButtonIfNecessary(foundBridges, bridgeView, root, bridgeChunkNr); addMoreButtonForBridges(bridgeView, root, bridgeChunkNr, foundBridges, featureCount);
} }
private void filterTunnelTree(String searchString) { private void filterTunnelTree(String searchString) {
List<Tunnel> foundTunnel = filterFeatures(searchString, model.getTunnels()); Supplier<Stream<Tunnel>> foundTunnel = () -> model.getTunnels().filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundTunnel.get().count();
TreeView<Renderable> tunnelView = mainWindow.getTunnelView(); TreeView<Renderable> tunnelView = mainWindow.getTunnelView();
TreeItem<Renderable> root = tunnelView.getRoot(); TreeItem<Renderable> root = tunnelView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildTunnelTreeFromList(foundTunnel, root); buildTunnelTreeFromList(foundTunnel, root);
updateTree(root); updateTree(root);
addMoreButtonIfNecessary(foundTunnel, tunnelView, root, tunnelChunkNr); addMoreButtonForTunnel(tunnelView, root, tunnelChunkNr, foundTunnel, featureCount);
} }
private void filterVegetationTree(String searchString) { private void filterVegetationTree(String searchString) {
List<Vegetation> foundVegetation = filterFeatures(searchString, model.getVegetation()); Supplier<Stream<Vegetation>> foundVegetation = () -> model.getVegetation().
filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundVegetation.get().count();
TreeView<Renderable> vegetationView = mainWindow.getVegetationView(); TreeView<Renderable> vegetationView = mainWindow.getVegetationView();
TreeItem<Renderable> root = vegetationView.getRoot(); TreeItem<Renderable> root = vegetationView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildVegetationTreeFromList(foundVegetation, root); buildVegetationTreeFromList(foundVegetation, root);
updateTree(root); updateTree(root);
addMoreButtonIfNecessary(foundVegetation, vegetationView, root, vegetationChunkNr); addMoreButtonForVegetation(vegetationView, root, vegetationChunkNr, foundVegetation, featureCount);
} }
private void filterTransportationTree(String searchString) { private void filterTransportationTree(String searchString) {
List<TransportationObject> foundTransportation = filterFeatures(searchString, model.getTransportation()); Supplier<Stream<TransportationObject>> foundTransportation = () -> model.getTransportation().
filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundTransportation.get().count();
TreeView<Renderable> transportationView = mainWindow.getTransportationView(); TreeView<Renderable> transportationView = mainWindow.getTransportationView();
TreeItem<Renderable> root = transportationView.getRoot(); TreeItem<Renderable> root = transportationView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildTransportationTreeFromList(foundTransportation, root); buildTransportationTreeFromList(foundTransportation, root);
updateTree(root); updateTree(root);
addMoreButtonIfNecessary(foundTransportation, transportationView, root, transportationChunkNr); addMoreButtonForTransportation(transportationView, root, transportationChunkNr,
foundTransportation, featureCount);
} }
private void filterWaterTree(String searchString) { private void filterWaterTree(String searchString) {
List<WaterObject> foundWater = filterFeatures(searchString, model.getWater()); Supplier<Stream<WaterObject>> foundWater = () -> model.getWater().filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundWater.get().count();
TreeView<Renderable> waterView = mainWindow.getWaterView(); TreeView<Renderable> waterView = mainWindow.getWaterView();
TreeItem<Renderable> root = waterView.getRoot(); TreeItem<Renderable> root = waterView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildWaterTreeFromList(foundWater, root); buildWaterTreeFromList(foundWater, root);
addMoreButtonIfNecessary(foundWater, waterView, root, waterChunkNr); addMoreButtonForWater(waterView, root, waterChunkNr, foundWater, featureCount);
} }
private void filterLandTree(String searchString) { private void filterLandTree(String searchString) {
List<CityObject> foundLand = filterFeatures(searchString, model.getLand()); Supplier<Stream<CityObject>> foundLand = () -> model.getLand().filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundLand.get().count();
TreeView<Renderable> landView = mainWindow.getTerrainView(); TreeView<Renderable> landView = mainWindow.getTerrainView();
TreeItem<Renderable> root = landView.getRoot(); TreeItem<Renderable> root = landView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildLandFromList(foundLand, root); buildLandTreeFromList(foundLand, root);
addMoreButtonIfNecessary(foundLand, landView, root, landChunkNr); addMoreButtonForLand(landView, root, landChunkNr, foundLand, featureCount);
} }
private void filterCityFurnitureTree(String searchString) { private void filterCityFurnitureTree(String searchString) {
List<CityFurniture> foundCityFurniture = filterFeatures(searchString, model.getCityFurniture()); Supplier<Stream<CityFurniture>> foundCityFurniture = () -> model.getCityFurniture().
filter(co -> featureFilter(co, searchString));
int featureCount = (int) foundCityFurniture.get().count();
TreeView<Renderable> cityFurnitureView = mainWindow.getCityFurnitureView(); TreeView<Renderable> cityFurnitureView = mainWindow.getCityFurnitureView();
TreeItem<Renderable> root = cityFurnitureView.getRoot(); TreeItem<Renderable> root = cityFurnitureView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildCityFurnitureTreeFromList(foundCityFurniture, root); buildCityFurnitureTreeFromList(foundCityFurniture, root);
addMoreButtonIfNecessary(foundCityFurniture, cityFurnitureView, root, cityFurnitureChunkNr); addMoreButtonForCityFurniture(cityFurnitureView, root, cityFurnitureChunkNr, foundCityFurniture, featureCount);
} }
private void filterGenericCityObjectTree(String searchString) { private void filterOtherCityObjectsTree(String searchString) {
List<GenericCityObject> foundGenericCityObject = filterFeatures(searchString, model.getGenericCityObjects()); Supplier<Stream<CityObject>> foundGenericCityObject = () -> model.getOtherCityObjects().
TreeView<Renderable> genericCityObjectView = mainWindow.getGenericCityObjectView(); filter(co ->featureFilter(co, searchString));
int featureCount = (int) foundGenericCityObject.get().count();
TreeView<Renderable> genericCityObjectView = mainWindow.getOtherCityObjectView();
TreeItem<Renderable> root = genericCityObjectView.getRoot(); TreeItem<Renderable> root = genericCityObjectView.getRoot();
root.getChildren().clear(); root.getChildren().clear();
buildGenericCityObjectTreeFromList(foundGenericCityObject, root); buildOtherCityObjectsTreeFromList(foundGenericCityObject, root);
addMoreButtonIfNecessary(foundGenericCityObject, genericCityObjectView, root, genericCityObjectsChunkNr); addMoreButtonForOtherCityObjects(genericCityObjectView, root, otherCityObjectsChunkNr,
foundGenericCityObject, featureCount);
} }
private <T extends CityObject> List<T> filterFeatures(String searchString, List<T> features) { private <T extends CityObject> List<T> filterFeatures(String searchString, List<T> features) {
...@@ -1421,6 +1351,10 @@ public class CityDoctorController { ...@@ -1421,6 +1351,10 @@ public class CityDoctorController {
return foundFeatures; return foundFeatures;
} }
private boolean featureFilter(CityObject co, String searchString) {
return co.getGmlId().getGmlString().contains(searchString);
}
public void resetSearch(FeatureType selectedTab) { public void resetSearch(FeatureType selectedTab) {
if (model == null) { if (model == null) {
return; return;
...@@ -1455,141 +1389,192 @@ public class CityDoctorController { ...@@ -1455,141 +1389,192 @@ public class CityDoctorController {
} }
mainWindow.resetSearchBar(); mainWindow.resetSearchBar();
root.getChildren().clear(); root.getChildren().clear();
List<Building> errorBuildings = new ArrayList<>();
for (Building b : model.getBuildings()) {
if (b.containsAnyError()) {
errorBuildings.add(b);
}
}
resetFeatureChunks(); resetFeatureChunks();
buildBuildingTreeFromList(errorBuildings, root); List<GmlId> foundBuildings = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getBuildingIds();
foundBuildings.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<Building>> supply = () -> model.getCache().getStream(foundBuildings).map(co -> (Building) co);
buildBuildingTreeFromList(supply, root);
updateTree(root); updateTree(root);
addMoreButtonToBuildingsIfNecessary(errorBuildings, buildingsView, root, buildingChunkNr); addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, supply, foundBuildings.size());
} }
public void fillTreeViewWithErrorVegetation() { public void fillTreeViewWithErrorVegetation() {
TreeView<Renderable> vegetationView = mainWindow.getVegetationView();
TreeItem<Renderable> root = vegetationView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getVegetationView(), model.getVegetation(), vegetationChunkNr); if (root == null) {
return;
}
mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundVegetation = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getVegetationIds();
foundVegetation.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<Vegetation>> supply = () -> model.getCache().getStream(foundVegetation).map(co -> (Vegetation) co);
buildVegetationTreeFromList(supply, root);
updateTree(root);
addMoreButtonForVegetation(vegetationView, root, vegetationChunkNr, supply, foundVegetation.size());
} }
public void fillTreeViewWithErrorBridges() { public void fillTreeViewWithErrorBridges() {
TreeView<Renderable> bridgeView = mainWindow.getBridgeView();
TreeItem<Renderable> root = bridgeView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getBridgeView(), model.getBridges(), bridgeChunkNr); if (root == null) {
return;
}
mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundBridge = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getBridgeIds();
foundBridge.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<BridgeObject>> supply = () -> model.getCache().getStream(foundBridge).map(co -> (BridgeObject) co);
buildBridgeTreeFromList(supply, root);
updateTree(root);
addMoreButtonForBridges(bridgeView, root, bridgeChunkNr, supply, foundBridge.size());
} }
public void fillTreeViewWithErrorLand() { public void fillTreeViewWithErrorLand() {
TreeView<Renderable> landView = mainWindow.getTerrainView();
TreeItem<Renderable> root = landView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getTerrainView(), model.getLand(), landChunkNr); if (root == null) {
return;
}
mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundLand = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getLandIds();
foundLand.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<CityObject>> supply = () -> model.getCache().getStream(foundLand).map(co -> (CityObject) co);
buildLandTreeFromList(supply, root);
updateTree(root);
addMoreButtonForLand(landView, root, landChunkNr, supply, foundLand.size());
} }
public void fillTreeViewWithErrorCityFurniture() { public void fillTreeViewWithErrorCityFurniture() {
TreeView<Renderable> cityFurnitureView = mainWindow.getCityFurnitureView();
TreeItem<Renderable> root = cityFurnitureView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getCityFurnitureView(), if (root == null) {
model.getCityFurniture(), cityFurnitureChunkNr); return;
}
mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundCityFurniture = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getCityFurnitureIds();
foundCityFurniture.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<CityFurniture>> supply = () -> model.getCache().getStream(foundCityFurniture).map(co -> (CityFurniture) co);
buildCityFurnitureTreeFromList(supply, root);
updateTree(root);
addMoreButtonForCityFurniture(cityFurnitureView, root, cityFurnitureChunkNr, supply, foundCityFurniture.size());
} }
public void fillTreeViewWithErrorGenericCityObjects() { public void fillTreeViewWithErrorOtherCityObjects() {
TreeView<Renderable> genericCityObjectsView = mainWindow.getOtherCityObjectView();
TreeItem<Renderable> root = genericCityObjectsView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getGenericCityObjectView(), if (root == null) {
model.getGenericCityObjects(), genericCityObjectsChunkNr); return;
}
mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundOtherCityObjects = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getOtherCityObjectsIds();
foundOtherCityObjects.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<CityObject>> supply = () -> model.getCache().getStream(foundOtherCityObjects).map(co -> (GenericCityObject) co);
buildOtherCityObjectsTreeFromList(supply, root);
updateTree(root);
addMoreButtonForOtherCityObjects(genericCityObjectsView, root, otherCityObjectsChunkNr, supply, foundOtherCityObjects.size());
} }
public void fillTreeViewWithErrorTransportation() { public void fillTreeViewWithErrorTransportation() {
TreeView<Renderable> transportationView = mainWindow.getTransportationView();
TreeItem<Renderable> root = transportationView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getTransportationView(), model.getTransportation(), if (root == null) {
transportationChunkNr);
}
public void fillTreeViewWithErrorTunnel() {
if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getTunnelView(), model.getTunnels(), tunnelChunkNr); mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundTransportation = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getTransportationIds();
foundTransportation.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<TransportationObject>> supply = () -> model.getCache().getStream(foundTransportation).map(co -> (TransportationObject) co);
buildTransportationTreeFromList(supply, root);
updateTree(root);
addMoreButtonForTransportation(transportationView, root, transportationChunkNr, supply, foundTransportation.size());
} }
public void fillTreeViewWithErrorWater() { public void fillTreeViewWithErrorTunnel() {
TreeView<Renderable> tunnelView = mainWindow.getTunnelView();
TreeItem<Renderable> root = tunnelView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
fillTreeViewWithErrorCityObjects(mainWindow.getWaterView(), model.getWater(), waterChunkNr);
}
private void fillTreeViewWithErrorCityObjects(TreeView<Renderable> treeView, List<? extends CityObject> objects,
AtomicInteger chunkCounter) {
TreeItem<Renderable> root = treeView.getRoot();
if (root == null) { if (root == null) {
return; return;
} }
mainWindow.resetSearchBar(); mainWindow.resetSearchBar();
root.getChildren().clear(); root.getChildren().clear();
List<CityObject> errorObjects = new ArrayList<>(); resetFeatureChunks();
for (CityObject co : objects) { List<GmlId> foundTunnel = model.getCache().getErrorFeatureIds();
if (co.containsAnyError()) { List<GmlId> idList = model.getTunnelIds();
errorObjects.add(co); foundTunnel.removeIf(gmlId -> (!idList.contains(gmlId)));
}
} Supplier<Stream<Tunnel>> supply = () -> model.getCache().getStream(foundTunnel).map(co -> (Tunnel) co);
buildTreeFromList(errorObjects, root, chunkCounter); buildTunnelTreeFromList(supply, root);
updateTree(root); updateTree(root);
addMoreButtonIfNecessary(errorObjects, treeView, root, chunkCounter); addMoreButtonForTunnel(tunnelView, root, tunnelChunkNr, supply, foundTunnel.size());
} }
public void fillTreeViewFromFeatures(FeatureType selectedTab) { public void fillTreeViewWithErrorWater() {
TreeView<Renderable> waterView = mainWindow.getWaterView();
TreeItem<Renderable> root = waterView.getRoot();
if (model == null) { if (model == null) {
return; return;
} }
mainWindow.resetSearchBar(); if (root == null) {
switch (selectedTab) { return;
case BUILDING:
buildBuildings(model);
updateTree(mainWindow.getBuildingsView().getRoot());
break;
case VEGETATION:
buildVegetation(model);
updateTree(mainWindow.getVegetationView().getRoot());
break;
case BRIDGE:
buildBridges(model);
updateTree(mainWindow.getBridgeView().getRoot());
break;
case LAND:
buildLand(model);
updateTree(mainWindow.getTerrainView().getRoot());
break;
case TRANSPORTATION:
buildTransportation(model);
updateTree(mainWindow.getTransportationView().getRoot());
break;
case TUNNEL:
buildTunnel(model);
updateTree(mainWindow.getTunnelView().getRoot());
break;
case WATER:
buildWater(model);
updateTree(mainWindow.getWaterView().getRoot());
break;
case CITY_FURNITURE:
buildCityFurniture(model);
updateTree(mainWindow.getCityFurnitureView().getRoot());
break;
case GENERIC_CITY_OBJECT:
buildOtherCityObjects(model);
updateTree(mainWindow.getGenericCityObjectView().getRoot());
break;
default:
throw new IllegalStateException();
} }
mainWindow.resetSearchBar();
root.getChildren().clear();
resetFeatureChunks();
List<GmlId> foundWater = model.getCache().getErrorFeatureIds();
List<GmlId> idList = model.getWaterIds();
foundWater.removeIf(gmlId -> (!idList.contains(gmlId)));
Supplier<Stream<WaterObject>> supply = () -> model.getCache().getStream(foundWater).map(co -> (WaterObject) co);
buildWaterTreeFromList(supply, root);
updateTree(root);
addMoreButtonForWater(waterView, root, tunnelChunkNr, supply, foundWater.size());
} }
public CityDoctorModel getModel() { public CityDoctorModel getModel() {
...@@ -1641,7 +1626,7 @@ public class CityDoctorController { ...@@ -1641,7 +1626,7 @@ public class CityDoctorController {
public void delete(TreeItem<Renderable> selectedItem) { public void delete(TreeItem<Renderable> selectedItem) {
if (model == null) { if (model == null) {
return; return;
}/* TODO: Rework this properly via Renderable implementation }/* Old debug function, would first need a refactor due to the RenderNode and GeoDB reworks
Renderable render = selectedItem.getValue(); Renderable render = selectedItem.getValue();
if (render instanceof BuildingNode node) { if (render instanceof BuildingNode node) {
model.getBuildings().remove(node.getBuilding()); model.getBuildings().remove(node.getBuilding());
...@@ -1654,37 +1639,19 @@ public class CityDoctorController { ...@@ -1654,37 +1639,19 @@ public class CityDoctorController {
public void errorFilterIndexChanged(Number newV) { public void errorFilterIndexChanged(Number newV) {
mainWindow.getMeshGroup().getChildren().clear(); mainWindow.getMeshGroup().getChildren().clear();
mainWindow.unselectEverything(); mainWindow.unselectEverything();
if (newV.intValue() == 0) { if (newV.intValue() == 0) { // Error filter was set to "All"
fillTreeViewFromFeatures(mainWindow.getSelectedTab()); buildTrees();
} else if (newV.intValue() == 1) { updateFeatureTrees();
switch (mainWindow.getSelectedTab()) { } else if (newV.intValue() == 1) { // Error filter was set to "With errors"
case BUILDING: fillTreeViewWithErrorBuildings();
fillTreeViewWithErrorBuildings(); fillTreeViewWithErrorVegetation();
break; fillTreeViewWithErrorBridges();
case VEGETATION: fillTreeViewWithErrorLand();
fillTreeViewWithErrorVegetation(); fillTreeViewWithErrorTransportation();
break; fillTreeViewWithErrorTunnel();
case BRIDGE: fillTreeViewWithErrorWater();
fillTreeViewWithErrorBridges(); fillTreeViewWithErrorCityFurniture();
break; fillTreeViewWithErrorOtherCityObjects();
case LAND:
fillTreeViewWithErrorLand();
break;
case TRANSPORTATION:
fillTreeViewWithErrorTransportation();
break;
case WATER:
fillTreeViewWithErrorWater();
break;
case CITY_FURNITURE:
fillTreeViewWithErrorCityFurniture();
break;
case GENERIC_CITY_OBJECT:
fillTreeViewWithErrorGenericCityObjects();
break;
default:
throw new IllegalStateException("Unknown selected feature tab: " + mainWindow.getSelectedTab());
}
} else { } else {
throw new IllegalStateException("Unknown filter index selected: " + newV); throw new IllegalStateException("Unknown filter index selected: " + newV);
} }
......
package de.hft.stuttgart.citydoctor2.gui;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.ErrorVisitor;
import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError;
import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError;
import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError;
import de.hft.stuttgart.citydoctor2.check.error.NestedRingError;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation;
import de.hft.stuttgart.citydoctor2.check.error.NotCeilingError;
import de.hft.stuttgart.citydoctor2.check.error.NotFloorError;
import de.hft.stuttgart.citydoctor2.check.error.NotGroundError;
import de.hft.stuttgart.citydoctor2.check.error.NotWallError;
import de.hft.stuttgart.citydoctor2.check.error.NullAreaError;
import de.hft.stuttgart.citydoctor2.check.error.PlanarityError;
import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonWithoutSurfaceError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.check.error.RingError;
import de.hft.stuttgart.citydoctor2.check.error.RingNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.RingSelfIntersectionError;
import de.hft.stuttgart.citydoctor2.check.error.RingTooFewPointsError;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.check.error.SolidError;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
public class GlobalErrorVisitor implements ErrorVisitor {
private MainWindow mainWindow;
public GlobalErrorVisitor(MainWindow mainWindow) {
this.mainWindow = mainWindow;
}
@Override
public void visit(RingError err) {
}
@Override
public void visit(PolygonError err) {
}
@Override
public void visit(RingSelfIntersectionError err) {
}
@Override
public void visit(PlanarityError err) {
}
@Override
public void visit(PolygonHoleOutsideError err) {
}
@Override
public void visit(NonManifoldEdgeError err) {
}
@Override
public void visit(MultipleConnectedComponentsError err) {
}
@Override
public void visit(NestedRingError err) {
}
@Override
public void visit(NonManifoldVertexError err) {
}
@Override
public void visit(PolygonWrongOrientationError err) {
}
@Override
public void visit(PolygonSameOrientationError err) {
}
@Override
public void visit(SolidNotClosedError err) {
}
@Override
public void visit(DependenciesNotMetError err) {
}
@Override
public void visit(UnknownCheckError err) {
}
@Override
public void visit(RingNotClosedError err) {
}
@Override
public void visit(ConsecutivePointSameError err) {
}
@Override
public void visit(AllPolygonsWrongOrientationError err) {
}
@Override
public void visit(PolygonInteriorDisconnectedError err) {
}
@Override
public void visit(NullAreaError err) {
}
@Override
public void visit(RingTooFewPointsError err) {
}
@Override
public void visit(NonPlanarPolygonNormalsDeviation err) {
}
@Override
public void visit(NonPlanarPolygonDistancePlaneError err) {
}
@Override
public void visit(PolygonIntersectingRingsError err) {
}
@Override
public void visit(SolidSelfIntError err) {
}
@Override
public void visit(TooFewPolygonsError err) {
}
@Override
public void visit(RingDuplicatePointError err) {
}
@Override
public void visit(RingEdgeIntersectionError err) {
}
@Override
public void visit(PointTouchesEdgeError err) {
}
@Override
public void visit(NotCeilingError err) {
}
@Override
public void visit(NotFloorError err) {
}
@Override
public void visit(NotWallError err) {
}
@Override
public void visit(NotGroundError err) {
}
@Override
public void visit(SchematronError se) {
mainWindow.getGlobalErrorsView().getItems().add(se.getErrorIdString() + " - " + se.getNameOfAttribute());
}
@Override
public void visit(SurfaceUnfragmentedError err) {
}
@Override
public void visit(DegeneratedRingError err) {
}
@Override
public void visit(AttributeMissingError err) {
mainWindow.getGlobalErrorsView().getItems().add(err.getErrorId().getIdString()
+ " - " + err.getNameOfAttribute());
}
@Override
public void visit(AttributeValueWrongError err) {
mainWindow.getGlobalErrorsView().getItems().add(err.getErrorId().getIdString()
+ " - " + err.getNameOfAttribute());
}
@Override
public void visit(AttributeInvalidError err) {
mainWindow.getGlobalErrorsView().getItems().add(err.getErrorId().getIdString()
+ " - " + err.getNameOfAttribute());
}
@Override
public void visit(PolygonWithoutSurfaceError err) {
}
@Override
public void visit(CheckError err) {
}
@Override
public void visit(SolidError err) {
}
}
...@@ -85,12 +85,6 @@ public class MainToolBar { ...@@ -85,12 +85,6 @@ public class MainToolBar {
@FXML @FXML
private ImageView lod4View; private ImageView lod4View;
@FXML
private Button zipManagerBtn;
@FXML
private ImageView zipManagerView;
@FXML @FXML
private Button aboutBtn; private Button aboutBtn;
...@@ -153,7 +147,6 @@ public class MainToolBar { ...@@ -153,7 +147,6 @@ public class MainToolBar {
setupReportButton(); setupReportButton();
setupResetCameraButton(); setupResetCameraButton();
setupHideRoofButton(); setupHideRoofButton();
setupZipManagerButton();
loadImages(); loadImages();
gridButton.setOnAction(ae -> renderer.showWireFrame(gridButton.isSelected())); gridButton.setOnAction(ae -> renderer.showWireFrame(gridButton.isSelected()));
...@@ -232,10 +225,6 @@ public class MainToolBar { ...@@ -232,10 +225,6 @@ public class MainToolBar {
Image img = new Image(inStream); Image img = new Image(inStream);
hideRoofView.setImage(img); hideRoofView.setImage(img);
} }
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/zip.png")) {
Image img = new Image(inStream);
zipManagerView.setImage(img);
}
} catch (IOException e) { } catch (IOException e) {
// ignore close exception // ignore close exception
} }
...@@ -347,14 +336,6 @@ public class MainToolBar { ...@@ -347,14 +336,6 @@ public class MainToolBar {
} }
private void setupZipManagerButton() {
zipManagerBtn.setDisable(true);
zipManagerBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.zip")));
zipManagerBtn.setOnAction(ae -> {
mainWindow.showZipManager();
});
}
public Button getCheckButton() { public Button getCheckButton() {
return checkBtn; return checkBtn;
} }
...@@ -407,10 +388,6 @@ public class MainToolBar { ...@@ -407,10 +388,6 @@ public class MainToolBar {
return resetCameraBtn; return resetCameraBtn;
} }
public Button getZipManagerBtn() {
return zipManagerBtn;
}
public HBox getToolBar() { public HBox getToolBar() {
return toolBar; return toolBar;
} }
......
...@@ -453,6 +453,7 @@ public class MainWindow extends Application { ...@@ -453,6 +453,7 @@ public class MainWindow extends Application {
}); });
} }
@SuppressWarnings("java:S2629")
private void checkForStartupLoading() { private void checkForStartupLoading() {
if (loadFileAtStartup) { if (loadFileAtStartup) {
logger.info(Localization.getText("MainWindow.loadGivenFile")); logger.info(Localization.getText("MainWindow.loadGivenFile"));
...@@ -638,7 +639,7 @@ public class MainWindow extends Application { ...@@ -638,7 +639,7 @@ public class MainWindow extends Application {
selectedTab = FeatureType.CITY_FURNITURE; selectedTab = FeatureType.CITY_FURNITURE;
break; break;
case 8: case 8:
selectedTab = FeatureType.GENERIC_CITY_OBJECT; selectedTab = FeatureType.OTHER_CITY_OBJECT;
break; break;
default: default:
throw new IllegalStateException("Unknown tab index: " + index); throw new IllegalStateException("Unknown tab index: " + index);
...@@ -672,7 +673,7 @@ public class MainWindow extends Application { ...@@ -672,7 +673,7 @@ public class MainWindow extends Application {
case CITY_FURNITURE: case CITY_FURNITURE:
cityFurnitureTab.setDisable(value); cityFurnitureTab.setDisable(value);
break; break;
case GENERIC_CITY_OBJECT: case OTHER_CITY_OBJECT:
otherObjectsTab.setDisable(value); otherObjectsTab.setDisable(value);
break; break;
default: default:
...@@ -801,10 +802,13 @@ public class MainWindow extends Application { ...@@ -801,10 +802,13 @@ public class MainWindow extends Application {
}); });
menu.getItems().add(copyToClipboardOption); menu.getItems().add(copyToClipboardOption);
/* Was used for debugging the repair module, functionless since the RenderNode rework.
* Commented out for now, might be needed later on again
MenuItem deleteOption = new MenuItem(Localization.getText("MainWindow.delete")); MenuItem deleteOption = new MenuItem(Localization.getText("MainWindow.delete"));
deleteOption.setOnAction(ae -> controller.delete(featureView.getSelectionModel().getSelectedItem())); deleteOption.setOnAction(ae -> controller.delete(featureView.getSelectionModel().getSelectedItem()));
menu.getItems().add(deleteOption); menu.getItems().add(deleteOption);
featureView.setContextMenu(menu); featureView.setContextMenu(menu);
*/
} }
public void fetchCopyAction(Renderable node) { public void fetchCopyAction(Renderable node) {
...@@ -1011,7 +1015,7 @@ public class MainWindow extends Application { ...@@ -1011,7 +1015,7 @@ public class MainWindow extends Application {
return attributeView; return attributeView;
} }
public TreeView<Renderable> getGenericCityObjectView() { public TreeView<Renderable> getOtherCityObjectView() {
return otherObjectsView; return otherObjectsView;
} }
...@@ -1157,7 +1161,7 @@ public class MainWindow extends Application { ...@@ -1157,7 +1161,7 @@ public class MainWindow extends Application {
case WATER -> new Pair<>(waterTab, waterView); case WATER -> new Pair<>(waterTab, waterView);
case LAND -> new Pair<>(terrainTab, terrainView); case LAND -> new Pair<>(terrainTab, terrainView);
case CITY_FURNITURE -> new Pair<>(cityFurnitureTab, cityFurnitureView); case CITY_FURNITURE -> new Pair<>(cityFurnitureTab, cityFurnitureView);
case GENERIC_CITY_OBJECT -> new Pair<>(otherObjectsTab, otherObjectsView); case OTHER_CITY_OBJECT -> new Pair<>(otherObjectsTab, otherObjectsView);
default -> throw new IllegalArgumentException("unknown feature type: " + coType); default -> throw new IllegalArgumentException("unknown feature type: " + coType);
}; };
} }
...@@ -1178,13 +1182,6 @@ public class MainWindow extends Application { ...@@ -1178,13 +1182,6 @@ public class MainWindow extends Application {
return mainToolBar.getOpenBtn(); return mainToolBar.getOpenBtn();
} }
public void showZipManager() {
controller.showZipManager();
}
public Button getZipManagerBtn() {
return mainToolBar.getZipManagerBtn();
}
public VertexClickHandler getClickHandler() { public VertexClickHandler getClickHandler() {
return clickHandler; return clickHandler;
......
...@@ -120,7 +120,7 @@ public class OpenFileDialog { ...@@ -120,7 +120,7 @@ public class OpenFileDialog {
if (fc == null) { if (fc == null) {
fc = new FileChooser(); fc = new FileChooser();
fc.setTitle(Localization.getText("OpenFileDialog.select")); fc.setTitle(Localization.getText("OpenFileDialog.select"));
fc.getExtensionFilters().add(new ExtensionFilter("GML/XML/ZIP", "*.gml", "*.xml", "*.zip")); fc.getExtensionFilters().add(new ExtensionFilter("GML/XML", "*.gml", "*.xml"));
fc.getExtensionFilters().add(new ExtensionFilter(Localization.getText("MainWindow.all"), "*.*")); fc.getExtensionFilters().add(new ExtensionFilter(Localization.getText("MainWindow.all"), "*.*"));
} }
File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, ""));
...@@ -153,9 +153,6 @@ public class OpenFileDialog { ...@@ -153,9 +153,6 @@ public class OpenFileDialog {
Thread t = new Thread(() -> { Thread t = new Thread(() -> {
try { try {
if (path.endsWith(".zip")) {
Platform.runLater(() -> progress.setProgress(-1));
}
controller.loadCityGml(path, numberOfRoundingPlaces, progress::setProgress, useValidation, controller.loadCityGml(path, numberOfRoundingPlaces, progress::setProgress, useValidation,
lowMemory); lowMemory);
Platform.runLater(() -> stage.close()); Platform.runLater(() -> stage.close());
......
...@@ -13,6 +13,7 @@ import javafx.scene.paint.PhongMaterial; ...@@ -13,6 +13,7 @@ import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.*; import javafx.scene.shape.*;
import java.util.*; import java.util.*;
import java.util.stream.Stream;
public class TriangulatedGeometry { public class TriangulatedGeometry {
...@@ -91,15 +92,15 @@ public class TriangulatedGeometry { ...@@ -91,15 +92,15 @@ public class TriangulatedGeometry {
addPolygonDataFromCityObjects(model.getVegetation(), triGeom, Color.LIGHTGREEN, filters); addPolygonDataFromCityObjects(model.getVegetation(), triGeom, Color.LIGHTGREEN, filters);
addPolygonDataFromCityObjects(model.getWater(), triGeom, Color.LIGHTSKYBLUE, filters); addPolygonDataFromCityObjects(model.getWater(), triGeom, Color.LIGHTSKYBLUE, filters);
addPolygonDataFromCityObjects(model.getCityFurniture(), triGeom, Color.BLUEVIOLET, filters); addPolygonDataFromCityObjects(model.getCityFurniture(), triGeom, Color.BLUEVIOLET, filters);
addPolygonDataFromCityObjects(model.getGenericCityObjects(), triGeom, Color.BLACK, filters); addPolygonDataFromCityObjects(model.getOtherCityObjects(), triGeom, Color.BLACK, filters);
return triGeom; return triGeom;
} }
private static void addPolygonDataFromCityObjects(List<? extends CityObject> cos, private static void addPolygonDataFromCityObjects(Stream<? extends CityObject> cos,
TriangulatedGeometry triGeom, Color color, List<ViewFilter> filters) { TriangulatedGeometry triGeom, Color color, List<ViewFilter> filters) {
CityObjectCollector collector = new CityObjectCollector(); CityObjectCollector collector = new CityObjectCollector();
cos.forEach(cityObject -> cityObject.accept(collector)); cos.forEach(cityObject -> cityObject.accept(collector));
collector.getCityObjects().forEach(cityObject -> addPolygonData(cityObject, triGeom, color, filters)); collector.getCityObjects().forEach(cityObject -> addPolygonData(cityObject, triGeom, color, filters));
......
package de.hft.stuttgart.citydoctor2.gui;
import de.hft.stuttgart.citydoctor2.gui.tree.ZipEntryListCell;
import de.hft.stuttgart.citydoctor2.gui.tree.node.ZipEntryNode;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
import de.hft.stuttgart.citydoctor2.zip.ZipEntryErrorType;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Predicate;
/**
* This class implements a GUI for managing a loaded {@link CityGmlZipArchive} in CityDoctor.
*/
public class ZipEntryManager {
private static final Logger logger = LogManager.getLogger(ZipEntryManager.class);
private Stage stage;
private CityGmlZipArchive archive;
@FXML
private TitledPane entriesPane;
@FXML
private TitledPane metadataPane;
@FXML
private Label subpathLbl;
@FXML
private TextField subpathValueTxt;
@FXML
private Label erroneousLbl;
@FXML
private Label erroneousValue;
@FXML
private Label filesizeLbl;
@FXML
private Label filesizeValue;
@FXML
private Label validatedLbl;
@FXML
private Label validatedValue;
@FXML
private Label objectCountLbl;
@FXML
private Label objectCountValue;
@FXML
private Button cancelBtn;
@FXML
private Button loadBtn;
@FXML
private ImageView loadImageView;
@FXML
private Button decompressBtn;
@FXML
private ImageView decompressImageView;
@FXML
private Button decompressAllBtn;
@FXML
private ImageView decompressAllImageView;
@FXML
private Button checkAllBtn;
@FXML
private ImageView checkAllImageView;
@FXML
private Button showReportBtn;
@FXML
private ImageView showReportImageView;
@FXML
private Button saveBtn;
@FXML
private ImageView saveImageView;
@FXML
private ListView<ZipEntryNode> entryList;
@FXML
private ProgressBar progress;
@FXML
private ProgressBar subProgress;
private CityDoctorController controller;
private int currentlyLoadedEntry = -1;
private CheckDialog dialog;
private final String unknownValueText = Localization.getText("ZipEntryManager.unknownValue");
private static final Predicate<ZipEntryNode> entryDecompressed = node ->
(node.getEntry().isLoaded() || node.getEntry().getErrorType() != null);
private static final Predicate<ZipEntryNode> entryValidated = entryDecompressed.and(node ->
(node.getEntry().getModel() != null && node.getEntry().getModel().isValidated()));
public ZipEntryManager(Window parent, CityDoctorController controller) throws IOException {
FXMLLoader loader = new FXMLLoader(ZipEntryManager.class.getResource("ZipEntryManager.fxml"));
loader.setController(this);
this.controller = controller;
archive = controller.getZipArchive();
VBox box = loader.load();
stage = new Stage();
stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.jpg")));
stage.setScene(new Scene(box));
stage.initOwner(parent);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle(Localization.getText("ZipEntryManager.title"));
stage.getScene().addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent event) -> {
if (event.getCode() == KeyCode.ESCAPE) {
stage.close();
}
});
dialog = new CheckDialog(null, parent, controller);
dialog.showZipArchiveOptions(true);
}
public void initialize() {
subProgress.setVisible(false);
entryList.getSelectionModel().selectedItemProperty().addListener((obs, oldI, newI) -> {
if (newI != null) {
showMetadata(newI.getEntry());
}
});
entryList.setCellFactory(param -> new ZipEntryListCell());
setupButtons();
applyLocalization();
populateZipEntryList();
}
private void setupButtons() {
try {
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/decompress_zipEntry.png")) {
Image img = new Image(inStream);
decompressImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/view_model.png")) {
Image img = new Image(inStream);
loadImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/decompress_all_zipEntries.png")) {
Image img = new Image(inStream);
decompressAllImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/check_all_zipEntries.png")) {
Image img = new Image(inStream);
checkAllImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/error_stat32x32.png")) {
Image img = new Image(inStream);
showReportImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/save.png")) {
Image img = new Image(inStream);
saveImageView.setImage(img);
}
} catch (IOException ignored) {
//ignore exceptions
}
decompressBtn.setOnAction(e -> {
disableTaskButtons();
setEntryListLocked(true);
Thread t = new Thread(() -> {
CityGmlZipEntry entry = entryList.getSelectionModel().getSelectedItem().getEntry();
logger.info("Decompressing entry \"{}\"", entry.getDisplayName());
controller.decompressZipEntry(entry, progressValue ->
Platform.runLater(() -> progress.setProgress(progressValue))
);
Platform.runLater(() -> {
refresh();
progress.setProgress(0);
setEntryListLocked(false);
});
});
t.setDaemon(true);
t.start();
});
loadBtn.setOnAction(e -> {
disableTaskButtons();
setEntryListLocked(true);
try {
int selectedIndex = entryList.getSelectionModel().getSelectedIndex();
if (selectedIndex == currentlyLoadedEntry) {
stage.hide();
return;
}
CityGmlZipEntry entry = entryList.getSelectionModel().getSelectedItem().getEntry();
if (entry.getErrorType() != null) {
logger.debug("IllegalState: loadBtn was pressed while an erroneous entry was selected");
populateZipEntryList(selectedIndex);
return;
}
controller.loadZipEntry(entry);
currentlyLoadedEntry = selectedIndex;
stage.hide();
} finally {
setEntryListLocked(false);
}
});
decompressAllBtn.setOnAction(e -> {
disableTaskButtons();
setEntryListLocked(true);
subProgress.setVisible(true);
subProgress.setProgress(0);
Thread t = new Thread(() -> {
progress.setProgress(0);
int count = 0;
int total = entryList.getItems().size();
for (ZipEntryNode node : entryList.getItems()) {
logger.info("Decompressing entry \"{}\"", node.getEntry().getDisplayName());
controller.decompressZipEntry(node.getEntry(), progressValue ->
Platform.runLater(() -> subProgress.setProgress(progressValue))
);
count++;
double progressValue = count * 1.0 / total;
Platform.runLater(() -> progress.setProgress(progressValue));
}
Platform.runLater(() -> {
subProgress.setVisible(false);
refresh();
progress.setProgress(0);
setEntryListLocked(false);
});
});
t.setDaemon(true);
t.start();
});
checkAllBtn.setOnAction(e -> {
disableTaskButtons();
dialog.show();
refresh();
});
showReportBtn.setOnAction(e -> {
disableTaskButtons();
setEntryListLocked(true);
try {
controller.loadZipEntry(entryList.getSelectionModel().getSelectedItem().getEntry());
if (currentlyLoadedEntry == -1) {
currentlyLoadedEntry = entryList.getSelectionModel().getSelectedIndex();
}
WriteReportDialog writeDialog = new WriteReportDialog(stage, controller, null);
writeDialog.show();
} catch (IOException ex) {
throw new RuntimeException(ex);
} finally {
controller.loadZipEntry(entryList.getItems().get(currentlyLoadedEntry).getEntry());
setEntryListLocked(false);
refresh();
}
});
showReportBtn.setDisable(true);
saveBtn.setOnAction(e -> {
disableTaskButtons();
setEntryListLocked(true);
try {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Export Zip file");
FileChooser.ExtensionFilter zipFilter = new FileChooser.ExtensionFilter("Zip File", "*.zip");
fileChooser.getExtensionFilters().add(zipFilter);
File f = fileChooser.showSaveDialog(stage.getOwner());
if (f != null) {
controller.saveZipArchiveReports(f);
}
} finally {
setEntryListLocked(false);
refresh();
}
});
saveBtn.setDisable(true);
cancelBtn.setOnAction(e -> stage.close());
}
private void applyLocalization() {
entriesPane.setText(Localization.getText("ZipEntryManager.entryListTitle"));
metadataPane.setText(Localization.getText("ZipEntryManager.metadata"));
subpathLbl.setText(Localization.getText("ZipEntryManager.subpathLbl"));
erroneousLbl.setText(Localization.getText("ZipEntryManager.erroneousLbl"));
filesizeLbl.setText(Localization.getText("ZipEntryManager.filesizeLbl"));
validatedLbl.setText(Localization.getText("ZipEntryManager.validatedLbl"));
objectCountLbl.setText(Localization.getText("ZipEntryManager.objectCountLbl"));
subpathValueTxt.setText(unknownValueText);
erroneousValue.setText(unknownValueText);
filesizeValue.setText(unknownValueText);
validatedValue.setText(unknownValueText);
objectCountValue.setText(unknownValueText);
loadBtn.setTooltip(new Tooltip(Localization.getText("ZipEntryManager.loadBtn")));
decompressBtn.setTooltip(new Tooltip(Localization.getText("ZipEntryManager.decompressBtn")));
decompressAllBtn.setTooltip(new Tooltip(Localization.getText("ZipEntryManager.decompressAllBtn")));
checkAllBtn.setTooltip(new Tooltip(Localization.getText("ZipEntryManager.checkAllBtn")));
showReportBtn.setTooltip(new Tooltip(Localization.getText("ZipEntryManager.showReportBtn")));
saveBtn.setTooltip(new Tooltip(Localization.getText("ZipEntryManager.saveBtn")));
cancelBtn.setText(Localization.getText("ZipEntryManager.cancelBtn"));
}
private void populateZipEntryList() {
populateZipEntryList(0);
}
private void populateZipEntryList(int selectionIndex) {
entryList.getItems().clear();
for (CityGmlZipEntry entry : archive.getEntries()) {
entryList.getItems().add(new ZipEntryNode(entry));
}
entryList.getSelectionModel().clearSelection();
entryList.getSelectionModel().select(selectionIndex);
showMetadata(entryList.getSelectionModel().getSelectedItem().getEntry());
decompressAllBtn.setDisable(entryList.getItems().stream().allMatch(entryDecompressed));
saveBtn.setDisable(entryList.getItems().stream().noneMatch(entryValidated));
}
private void showMetadata(CityGmlZipEntry entry) {
subpathValueTxt.setText(entry.getEntrySubPath());
if (entry.getFileSize() != -1L) {
long fileSize = entry.getFileSize();
long kb = 1024L;
long mb = kb * kb;
long gb = mb * kb;
if (fileSize < kb) {
filesizeValue.setText("< 1 KB");
} else if (fileSize < mb) {
filesizeValue.setText(String.format("%s KB", fileSize / kb));
} else if (fileSize < gb) {
filesizeValue.setText(String.format("%s MB", fileSize / mb));
} else {
double gigabytes = (double) fileSize / gb;
filesizeValue.setText(String.format("%.2f GB", gigabytes));
}
} else {
filesizeValue.setText(unknownValueText);
}
if (entry.getErrorType() != null) {
erroneousValue.setText(getErrorText(entry.getErrorType()));
validatedValue.setText(unknownValueText);
objectCountValue.setText(unknownValueText);
loadBtn.setDisable(true);
decompressBtn.setDisable(true);
showReportBtn.setDisable(true);
} else {
erroneousValue.setText(Localization.getText("ZipEntryManager.no"));
loadBtn.setDisable(!entry.isLoaded());
decompressBtn.setDisable(entry.isLoaded());
if (entry.getModel() == null) {
validatedValue.setText(unknownValueText);
objectCountValue.setText(unknownValueText);
return;
}
if (entry.getModel().isValidated()) {
validatedValue.setText(Localization.getText("ZipEntryManager.yes"));
showReportBtn.setDisable(false);
} else {
validatedValue.setText(Localization.getText("ZipEntryManager.no"));
showReportBtn.setDisable(true);
}
objectCountValue.setText(String.valueOf(entry.getModel().getNumberOfFeatures()));
}
}
private void disableTaskButtons() {
decompressBtn.setDisable(true);
loadBtn.setDisable(true);
decompressAllBtn.setDisable(true);
showReportBtn.setDisable(true);
saveBtn.setDisable(true);
}
public void refresh() {
populateZipEntryList(entryList.getSelectionModel().getSelectedIndex());
}
private String getErrorText(ZipEntryErrorType error) {
switch (error) {
case EXCESSIVE_FILESIZE -> {
return Localization.getText("ZipEntryManager.excessiveFileSize");
}
case INVALID_CITY_GML_FILE -> {
return Localization.getText("ZipEntryManager.invalidCityGml");
}
default -> {
return Localization.getText("ZipEntryManager.ioError");
}
}
}
private void setEntryListLocked(boolean locked) {
entryList.setMouseTransparent(locked);
entryList.setFocusTraversable(!locked);
}
public void show() {
Platform.runLater(() -> stage.showAndWait());
refresh();
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.gui.CityDoctorController;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AddMoreButtonRunnable implements Runnable{
private int featureCount;
private final TreeView<Renderable> view;
private final TreeItem<Renderable> root;
private final AtomicInteger chunkCounter;
private static final int MAX_FEATURES_PER_CHUNK = CityDoctorController.getMaxFeaturesPerChunk();
protected AddMoreButtonRunnable(int featureCount, TreeView<Renderable> view,
TreeItem<Renderable> root, AtomicInteger chunkCounter){
this.featureCount = featureCount;
this.view = view;
this.root = root;
this.chunkCounter = chunkCounter;
}
@Override
public void run() {
// 29 is the height of one item
int numberOfDisplayedItems = (int) (view.getHeight() / 29);
int selectedIndex = view.getSelectionModel().getSelectedIndex();
// remove button node
root.getChildren().remove(root.getChildren().size() - 1);
chunkCounter.getAndIncrement();
int visibleFeatures = countVisibleNodes(view);
buildNodeTreeCall();
if (selectedIndex >= 0) {
view.getSelectionModel().select(selectedIndex);
}
if ((chunkCounter.get() + 1) * MAX_FEATURES_PER_CHUNK < featureCount) {
root.getChildren().add(new TreeItem<>(new ButtonRenderable(this)));
}
view.scrollTo(visibleFeatures - numberOfDisplayedItems + 1);
}
/**
* Function hook for the buildTree call of the view
*/
public abstract void buildNodeTreeCall();
private static int countVisibleNodes(TreeView<Renderable> view) {
return countVisibleNodes(view.getRoot()) + 1;
}
private static int countVisibleNodes(TreeItem<Renderable> root) {
int visibleFeatures = root.getChildren().size();
for (TreeItem<Renderable> child : root.getChildren()) {
if (!child.getChildren().isEmpty() && child.isExpanded()) {
visibleFeatures += countVisibleNodes(child);
}
}
return visibleFeatures;
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.gui.tree.node.ZipEntryNode;
import javafx.scene.control.ListCell;
public class ZipEntryListCell extends ListCell<ZipEntryNode> {
@Override
protected void updateItem(ZipEntryNode item, boolean empty) {
super.updateItem(item, empty);
if (!empty || item != null) {
setText(item.getText());
updateColor();
} else {
setText(null);
}
}
public void updateColor() {
setTextFill(getItem().getTextColor());
}
}
...@@ -12,9 +12,11 @@ public class CityObjectNode extends Renderable { ...@@ -12,9 +12,11 @@ public class CityObjectNode extends Renderable {
private static final Logger logger = LogManager.getLogger(CityObjectNode.class); private static final Logger logger = LogManager.getLogger(CityObjectNode.class);
private final CityObject co; private final CityObject co;
private String text;
public CityObjectNode(CityObject co) { public CityObjectNode(CityObject co) {
this.co = co; this.co = co;
this.text = co.getDisplayText();
} }
@Override @Override
...@@ -30,7 +32,7 @@ public class CityObjectNode extends Renderable { ...@@ -30,7 +32,7 @@ public class CityObjectNode extends Renderable {
@Override @Override
public String getText() { public String getText() {
return co.getDisplayText(); return text;
} }
@Override @Override
......
package de.hft.stuttgart.citydoctor2.gui.tree.node;
import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry;
import javafx.scene.paint.Color;
public class ZipEntryNode {
private final CityGmlZipEntry entry;
public ZipEntryNode(CityGmlZipEntry entry) {
this.entry = entry;
}
public Color getTextColor() {
if (entry.getErrorType() != null) {
return Color.DARKRED;
} else if (entry.getModel() != null) {
if (entry.getModel().getNumberOfFeatures() == 0) {
return Color.GRAY;
}
if (entry.getModel().isValidated()) {
if (entry.getModel().collectErrors().isEmpty()) {
return Color.GREEN;
}
return Color.RED;
}
return Color.BLUE;
} else if (entry.isLoaded()) {
return Color.BLUE;
} else {
return Color.BLACK;
}
}
public String getText() {
return entry.getDisplayName();
}
public CityGmlZipEntry getEntry() {
return entry;
}
}
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?> <?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.Tab?> <?import javafx.scene.control.Tab?>
...@@ -52,78 +51,6 @@ ...@@ -52,78 +51,6 @@
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy> </columnResizePolicy>
</TableView> </TableView>
<VBox fx:id="zipArchiveOptionsVBox" prefHeight="176.0" prefWidth="485.0">
<children>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<CheckBox fx:id="streamCheckOption" mnemonicParsing="false"
text="Use low memory mode">
<font>
<Font size="14.0"/>
</font>
</CheckBox>
<Label fx:id="streamCheckLabel" text="(?)" underline="true">
<opaqueInsets>
<Insets/>
</opaqueInsets>
<padding>
<Insets left="3.0"/>
</padding>
<font>
<Font size="14.0"/>
</font>
</Label>
</children>
</HBox>
<VBox fx:id="streamCheckParametersVBox" disable="true" prefHeight="200.0"
prefWidth="100.0">
<children>
<Label fx:id="outputPathLabel" text="Output path:">
<font>
<Font size="14.0"/>
</font>
</Label>
<HBox prefWidth="485.0">
<children>
<TextField fx:id="outputPathTextField" prefHeight="25.0"
prefWidth="291.0">
<font>
<Font size="14.0"/>
</font>
</TextField>
<Button fx:id="outputPathBtn" mnemonicParsing="false" prefHeight="30.0"
prefWidth="86.0" text="Select">
<font>
<Font size="14.0"/>
</font>
</Button>
</children>
</HBox>
<CheckBox fx:id="pdfReportsOption" mnemonicParsing="false"
text="Create PDF reports">
<padding>
<Insets top="10.0"/>
</padding>
<font>
<Font size="14.0"/>
</font>
</CheckBox>
<CheckBox layoutX="10.0" layoutY="60.0" mnemonicParsing="false"
text="Create XML reports" fx:id="xmlReportsOption">
<padding>
<Insets top="10.0"/>
</padding>
<font>
<Font size="14.0"/>
</font>
</CheckBox>
</children>
</VBox>
</children>
<HBox.margin>
<Insets left="30.0"/>
</HBox.margin>
</VBox>
</children> </children>
</HBox> </HBox>
<HBox spacing="5.0" VBox.vgrow="NEVER"> <HBox spacing="5.0" VBox.vgrow="NEVER">
......
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