diff --git a/.gitignore b/.gitignore index 23bdc0269243f92a450ef9d861f5b638243e9763..51eea88ba4d59c340188a89f889de3a3ed3b9383 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ /CityDoctorParent/.idea/jarRepositories.xml /CityDoctorParent/.idea/misc.xml /CityDoctorParent/.idea/vcs.xml +/CityDoctorParent/.idea .idea /GUISettings.properties diff --git a/.run/CityDoctorGUIStarter.run.xml b/.run/CityDoctorGUIStarter.run.xml new file mode 100644 index 0000000000000000000000000000000000000000..b803b46bf77ea965e6433c4a4062469c427aca4a --- /dev/null +++ b/.run/CityDoctorGUIStarter.run.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/.run/Maven Verify.run.xml b/.run/Maven Verify.run.xml new file mode 100644 index 0000000000000000000000000000000000000000..c2ca0a344e8eb6404e5a22ef81132ebe9be868a7 --- /dev/null +++ b/.run/Maven Verify.run.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/.run/Run all tests.run.xml b/.run/Run all tests.run.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa53e1242ad1d9e280d3c0691018aeb842414bae --- /dev/null +++ b/.run/Run all tests.run.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.run/Test Docker deployment.run.xml b/.run/Test Docker deployment.run.xml new file mode 100644 index 0000000000000000000000000000000000000000..caa12557f57406aae9ed1c03ef260f3b8e39e8c6 --- /dev/null +++ b/.run/Test Docker deployment.run.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CityDoctorParent/CityDoctorCheckResult/pom.xml b/CityDoctorParent/CityDoctorCheckResult/pom.xml index 6a9d0d2c0f84cd723536a134dc5c72735ecb58bb..e1c3b8502b8b9f2e23bc3050f0a013f2bc30ba8b 100644 --- a/CityDoctorParent/CityDoctorCheckResult/pom.xml +++ b/CityDoctorParent/CityDoctorCheckResult/pom.xml @@ -6,7 +6,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 CityDoctorCheckResult diff --git a/CityDoctorParent/CityDoctorEdge/pom.xml b/CityDoctorParent/CityDoctorEdge/pom.xml index e7a5d0ab4acb426bea35b571123d2ffa3b66fb53..25e060796130f9b8f80768174c09db7d78802fb7 100644 --- a/CityDoctorParent/CityDoctorEdge/pom.xml +++ b/CityDoctorParent/CityDoctorEdge/pom.xml @@ -6,7 +6,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 CityDoctorEdge diff --git a/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java b/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java index 89fa9deffd0fe7a9999b6d9db6577ca5a541e9f0..a3f4f87fdde019bbad16dcd8aedacafa8d5f82b5 100644 --- a/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java +++ b/CityDoctorParent/CityDoctorEdge/src/test/java/de/hft/stuttgart/citydoctor2/edge/MeshSurfaceUtilsTest.java @@ -1255,11 +1255,11 @@ public class MeshSurfaceUtilsTest { assertTrue(intersectPolygons.isEmpty()); } - @Test(timeout = 10000) + @Test/*(timeout = 10000)*/ public void testKaiserwallComplexBuilding() throws CityGmlParseException, InvalidGmlFileException { ParserConfiguration config = new ParserConfiguration(8, false); CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/KaiserwallComplexBuilding.gml", config); - Building building = model.getBuildings().get(0); + Building building = model.getBuildings().toList().get(0); Geometry geom = building.getBuildingInstallations().get(0).getGeometries().get(0); assertNotNull(geom); MeshSurface surface = MeshSurface.of(geom); diff --git a/CityDoctorParent/CityDoctorModel/pom.xml b/CityDoctorParent/CityDoctorModel/pom.xml index b02bd6e5fed526a042211232aff7241085d21be9..815c086adb29f12a2afc91601c2e39781cf7408e 100644 --- a/CityDoctorParent/CityDoctorModel/pom.xml +++ b/CityDoctorParent/CityDoctorModel/pom.xml @@ -6,7 +6,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 ${project.version}-${git.commit.id.abbrev} @@ -38,11 +38,6 @@ org.jogamp.jogl jogl-all-main - - junit - junit - test - org.apache.logging.log4j log4j-api @@ -77,6 +72,18 @@ io.github.earcut4j earcut4j + + org.orbisgis + h2gis + + + com.github.ben-manes.caffeine + caffeine + + + com.zaxxer + HikariCP + diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java index e81369a1496db63586c44fad4181c7e0ae6bf1dc..9a3b136d3e03f2b824938a4ae05473bb928f1947 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java @@ -154,6 +154,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param checkable a checkable */ + @Override public void check(Checkable checkable) { } @@ -163,6 +164,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param ab building or building part */ + @Override public void check(AbstractBuilding ab) { } @@ -172,6 +174,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param bs a boundary surface */ + @Override public void check(BoundarySurface bs) { } @@ -181,6 +184,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param bo a bridge */ + @Override public void check(BridgeObject bo) { } @@ -190,6 +194,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param b a building */ + @Override public void check(Building b) { } @@ -199,6 +204,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param bi a building installation */ + @Override public void check(Installation bi) { } @@ -208,6 +214,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param bp a building part */ + @Override public void check(BuildingPart bp) { } @@ -217,6 +224,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param co a city object */ + @Override public void check(CityObject co) { } @@ -226,6 +234,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param lo a land use object */ + @Override public void check(LandObject lo) { } @@ -235,6 +244,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param o an opening */ + @Override public void check(Opening o) { } @@ -244,6 +254,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param to a transportation object */ + @Override public void check(TransportationObject to) { } @@ -253,6 +264,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param veg a vegetation object */ + @Override public void check(Vegetation veg) { } @@ -262,6 +274,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param wo a water object */ + @Override public void check(WaterObject wo) { } @@ -271,6 +284,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param geom a geometry */ + @Override public void check(Geometry geom) { } @@ -280,6 +294,7 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param poly a polygon */ + @Override public void check(Polygon poly) { } @@ -289,26 +304,36 @@ public abstract non-sealed class Check implements CheckableVisitor { * * @param ring a linear ring */ + @Override public void check(LinearRing ring) { } - + + @Override public void check(TinObject tin) { } - + + @Override public void check(ReliefObject relief) { } + @Override public void check(CityFurniture cf){ } + @Override public void check(GenericCityObject gco) { } + @Override + public void check(OtherConstructionObject oco){ + + } + /** * The initialization method of this check. It will be called before any check * method will be executed. Override this if you want to have configurable diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java index c9b941243b99b37ea58449057e8fe05e416762bd..3994bdd18a60570ad6365f58b62dd88a9c30336f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java @@ -52,7 +52,7 @@ public abstract class Checkable implements Serializable { private final Map checkResults = new HashMap<>(); private boolean isValidated = false; - protected void setValidated(boolean validated) { + public void setValidated(boolean validated) { isValidated = validated; } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableUtilsVisitor.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableUtilsVisitor.java index 0034c8c093c7cd4691deb8f0dfe9dbcbde915525..22d5d94d3d652305f6225e500adefe559d583f5b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableUtilsVisitor.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableUtilsVisitor.java @@ -31,6 +31,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Installation; import de.hft.stuttgart.citydoctor2.datastructure.LandObject; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject; import de.hft.stuttgart.citydoctor2.datastructure.TinObject; @@ -165,4 +166,8 @@ public abstract non-sealed class CheckableUtilsVisitor implements CheckableVisit } + @Override + public void check(OtherConstructionObject oco){ + + } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableVisitor.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableVisitor.java index 7830c5a8b155f3529bbae00a82b9640387d394b8..6cbc1ada4e5bda030a5a43cc638b99cc0e7a42c3 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableVisitor.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckableVisitor.java @@ -13,6 +13,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Installation; import de.hft.stuttgart.citydoctor2.datastructure.LandObject; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.Opening; +import de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject; import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject; import de.hft.stuttgart.citydoctor2.datastructure.TinObject; @@ -69,4 +70,6 @@ public sealed interface CheckableVisitor permits Check, CheckableUtilsVisitor { void check(GenericCityObject gco); + void check(OtherConstructionObject oco); + } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/CityObjectCache.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/CityObjectCache.java new file mode 100644 index 0000000000000000000000000000000000000000..30b5fc69c15560cfa66663389e1466264b27d63a --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/CityObjectCache.java @@ -0,0 +1,69 @@ +package de.hft.stuttgart.citydoctor2.database; + +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; + +import java.util.List; +import java.util.stream.Stream; + +public interface CityObjectCache { + + /** + * Inserts a CityObject into this cache. Overwrites any existing CityObject with the same GmlID. + * @param cityObject + */ + void put(CityObject cityObject); + + /** + * Gets a CityObject from this cache by their GmlID + * @param id GmlID of the requested Object + * @return the associated CityObject, or null if no Object has a matching GmlID + */ + CityObject get(GmlId id); + + /** + * Replaces a CityObject with another one + * @param id GmlID of the CityObject that is to be replaced + * @param cityObject the replacement + */ + void replace(GmlId id, CityObject cityObject); + + /** + * Returns a Stream of CityObjects from a list of GmlIDs + * @param ids the list of GmlIDs + * @return CityObject Stream of the IDs + */ + Stream getStream(List ids); + + /** + * Returns the total count of entries. + * @return the count + */ + int getTotalFeatureCount(); + + /** + * Resets the Cache to its initial state + */ + void resetCache(); + + /** + * Returns a list of GmlIDs, whose associated CityObjects were found to contain at least one error. + *

+ * Requires Validation to be run first, as unvalidated CityObjects are of unknown state. + * @return list of GmlIDs which were found to contain an error + */ + List getErrorFeatureIds(); + + /** + * Sets this cache into parsing mode, returning an AutoClosable representing the scoped-state of parsing operation. + * @return an AutoClosable representing the scoped-state for parsing + */ + AutoCloseable startParsingMode(); + + /** + * Sets this cache into checking mode, returning an AutoClosable representing the scoped-state of checking operation. + * @return an AutoClosable representing the scoped-state for checking + */ + AutoCloseable startCheckingMode(); + +} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDatabaseHandler.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDatabaseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..e7820948571278352564ccbcee6e03782c3cdc8a --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDatabaseHandler.java @@ -0,0 +1,330 @@ +package de.hft.stuttgart.citydoctor2.database; + +import com.zaxxer.hikari.HikariDataSource; + +import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor; +import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; + +import de.hft.stuttgart.citydoctor2.utils.Localization; +import org.apache.commons.lang3.SerializationException; +import org.apache.commons.lang3.SerializationUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.h2gis.functions.factory.H2GISDBFactory; +import org.h2gis.utilities.wrapper.DataSourceWrapper; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InvalidClassException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Utility class for setup and access of the embedded database. + */ +public class EmbeddedDatabaseHandler { + + private static final Logger logger = LogManager.getLogger(EmbeddedDatabaseHandler.class); + private static final String DB_NAME = "/database/cd_db"; + private DataSourceWrapper dataSource; + + public EmbeddedDatabaseHandler(){ + try { + String jdbcurl = H2GISDBFactory.createDataSource(DB_NAME, + true, ";AUTO_SERVER=TRUE").getConnection().getMetaData().getURL(); + + logger.debug("1] {}",jdbcurl); + HikariDataSource ds = new HikariDataSource(); + + ds.setJdbcUrl(jdbcurl); + ds.setUsername("sa"); + ds.setPassword("sa"); + int coreCount = Runtime.getRuntime().availableProcessors(); + ds.setMaximumPoolSize(coreCount*5); + ds.setMinimumIdle(coreCount*5); + + dataSource = new DataSourceWrapper(ds); + setupFeaturesTable(); + //Cleanup hook + Runtime.getRuntime().addShutdownHook(new Thread(ds::close)); + } catch (Exception e) { + logger.fatal(Localization.getText("DatabaseHandler.setupFailure")); + logger.fatal(e.getMessage()); + } + + + } + + + public void setupFeaturesTable() { + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement dropPs = con.prepareStatement("DROP TABLE IF EXISTS features")){ + dropPs.executeUpdate(); + if (logger.isDebugEnabled()) { + logger.debug("Dropped existing features table"); + } + } + try (PreparedStatement createPs = con.prepareStatement("CREATE TABLE features (gmlid VARCHAR(255)" + + " PRIMARY KEY, bbox GEOMETRY, data BLOB, errors BOOLEAN);")) { + createPs.executeUpdate(); + if (logger.isDebugEnabled()) { + logger.debug("Created features table"); + } + //CREATE SPATIAL INDEX GEO_TABLE_SPATIAL_INDEX ON GEO_TABLE(THE_GEOM); <- Create spatial id + } + + } catch (SQLException e) { + logger.fatal(Localization.getText("DatabaseHandler.tableFailure")); + logger.fatal(e.getMessage()); + } + } + + /** + * Saves a CityObject to the embedded database, updating the entry if it already exists. + * @param co the CityObject + */ + public void marshallCityObject(CityObject co) { + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement("MERGE INTO features VALUES (?, ?, ?, ?)")) { + ps.setString(1, co.getGmlId().toString()); + String bbox = BoundingBox.of(co).to2DWkt(); + ps.setString(2, bbox); + ps.setBoolean(4, co.containsAnyError()); + + if (logger.isDebugEnabled()) { + logger.debug("Attempting to serialize CityObject: {} ", co); + } + try { + byte[] bytes = SerializationUtils.serialize(co); + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ps.setBinaryStream(3, bis, bytes.length); + ps.executeUpdate(); + } catch (SerializationException e) { + logger.error(e.getMessage()); + logger.error(co.getGmlId()); + + } + } + } catch (SQLException e) { + logger.error(Localization.getText("DatabaseHandler.marshallingFailure"), co.getGmlId()); + logger.error(e.getMessage()); + } + } + + /** + * Tries to save all CityObjects in a Map to the embedded database as a batched statement, updating already existing entries. + * @param map a Map containing the CityObjects + * @return true if the batched statement was successfully created and commited, false otherwise + */ + public boolean tryMarshallCityObjectMap(Map map) { + // Id String for error logging + String id = ""; + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement("MERGE INTO features VALUES (?, ?, ?, ?)")) { + con.setAutoCommit(false); + for (Map.Entry entry : map.entrySet()) { + CityObject co = entry.getValue(); + id = entry.getKey().toString(); + ps.setString(1, id); + String bbox = BoundingBox.of(co).to2DWkt(); + ps.setString(2, bbox); + if (logger.isTraceEnabled()) { + logger.trace("Attempting to serialize CityObject: {} ", co); + } + ps.setBoolean(4, co.containsAnyError()); + + try { + byte[] bytes = SerializationUtils.serialize(co); + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ps.setBinaryStream(3, bis, bytes.length); + ps.addBatch(); + } catch (SerializationException e) { + logger.error(Localization.getText("DatabaseHandler.serializationFailure"),co.getGmlId()); + logger.error(e.getMessage()); + } + } + ps.executeBatch(); + con.commit(); + } catch (SQLException e) { + con.rollback(); + logger.error(Localization.getText("DatabaseHandler.batchCommitFailure"), id); + logger.error(e.getMessage()); + return false; + } finally{ + con.setAutoCommit(true); + } + } catch (SQLException e){ + logger.error(Localization.getText("DatabaseHandler.connectionFailure")); + logger.error(e.getMessage()); + return false; + } + return true; + } + + /** + * Retrieves a CityObject from the embedded database. + * @param id the gmlId of the requested Feature + * @return the Feature, or null if no entry was found + */ + public CityObject unmarshallCityObject(GmlId id) { + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement( + "SELECT data FROM features WHERE gmlid = ?")) { + ps.setString(1, id.toString()); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + try (InputStream is = rs.getBinaryStream("data")) { + CityObject co = SerializationUtils.deserialize(is); + // Rebuild the adjacency maps + co.accept(new CheckableUtilsVisitor() { + @Override + public void check(Geometry geom) { + geom.updateVertices(); + } + }); + return co; + } catch (InvalidClassException | ClassCastException | SerializationException e){ + String msg = String.format("Deserialization of CityObject \"%s\" failed",id); + logger.error(msg,e); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } catch (SQLException e) { + logger.error(Localization.getText("DatabaseHandler.unmarshallingFailure"), id); + logger.error(e.getMessage()); + } + + return null; + } + + /** + * Retrieves a List of GmlIds of CityObjects that contain any {@link de.hft.stuttgart.citydoctor2.check.CheckError CheckError}. + * @return a List of GmlIds of CityObjects containing any CheckError + */ + public List getIdsOfAllCityObjectsWithErrors(){ + List ids = new ArrayList<>(); + try (Connection con = dataSource.getConnection()){ + try (PreparedStatement ps = con.prepareStatement("SELECT gmlid FROM features WHERE errors = TRUE")) { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + ids.add(new GmlId(rs.getString("gmlid"))); + } + } + } catch (SQLException e) { + logger.error(Localization.getText("DatabaseHandler.fetchErrorIdsFailure")); + logger.error(e.getMessage()); + } + return ids; + } + + + /** + * Retrieves a List of GmlIds of CityObjects that are candidates for a buffer collision with a given CityObject(subject), + * meaning the candidate's bbox intersects the subject's buffered bbox. + * @param subject the subject CityObject + * @param bufferSize the buffer distance + * @return a List of GmlIds of buffer collision candidates + */ + public List getBufferCollisionCandidates(CityObject subject, double bufferSize) { + return getBufferCollisionCandidates(subject.getGmlId(), bufferSize); + } + + /** + * Retrieves a List of GmlIds of CityObjects that are candidates for a buffer collision with a given CityObject(subject), + * meaning the candidate's bbox intersects the subject's buffered bbox. + * @param subjectId the subject CityObject's GmlId + * @param bufferSize the buffer distance + * @return a List of GmlIds of buffer collision candidates + */ + public List getBufferCollisionCandidates(GmlId subjectId, double bufferSize) { + List intersectingObjects = new ArrayList<>(); + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement("SELECT gmlid FROM features AS tab1" + + " WHERE ST_INTERSECTS(ST_BUFFER(tab1.bbox,?), (SELECT bbox FROM features WHERE gmlid = ?)) " + + "AND tab1.gmlid <> ?")) { + ps.setDouble(1, bufferSize); + ps.setString(2, subjectId.toString()); + ps.setString(3, subjectId.toString()); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + intersectingObjects.add(new GmlId(rs.getString("gmlid"))); + } + } + } catch (SQLException e) { + logger.error(Localization.getText("DatabaseHandler.getBufferIntersectFailure"),subjectId); + logger.debug(e.getMessage()); + } + return intersectingObjects; + } + + /** + * Retrieves a List of GmlIds of CityObjects that are candidates for a geometry collision with a given CityObject(subject), + * meaning the bounding boxes of candidate and subject intersect. + * @param subject the subject CityObject + * @return a List of GmlIds of buffer collision candidates + */ + public List getGeometryCollisionCandidates(CityObject subject) { + return getGeometryCollisionCandidates(subject.getGmlId()); + } + + /** + * Retrieves a List of GmlIds of CityObjects that are candidates for a geometry collision with a given CityObject(subject), + * meaning the bounding boxes of candidate and subject intersect. + * @param subjectId the subject CityObject + * @return a List of GmlIds of buffer collision candidates + */ + public List getGeometryCollisionCandidates(GmlId subjectId) { + List intersectingObjects = new ArrayList<>(); + + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement("SELECT gmlid FROM features AS tab1" + + " WHERE ST_INTERSECTS(tab1.bbox, (SELECT bbox FROM features WHERE gmlid = ?)) AND tab1.gmlid <> ?")) + { + ps.setString(1, subjectId.toString()); + ps.setString(2, subjectId.toString()); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + intersectingObjects.add(new GmlId(rs.getString("gmlid"))); + } + } + } catch (SQLException e) { + logger.error(Localization.getText("DatabaseHandler.getBBoxIntersectFailure"),subjectId); + logger.debug(e.getMessage()); + } + return intersectingObjects; + } + + /** + * Returns the number of top-level CityObjects entries that are currently in the embedded database. + * @return the count of top-level CityObjects in the database + */ + public int getFeatureCount() { + int count = -1; + + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(gmlid) AS nr FROM features")) { + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + count = rs.getInt("nr"); + } + } + } catch (SQLException e) { + logger.error(Localization.getText("DatabaseHandler.getFeatureCountFailure")); + logger.debug(e.getMessage()); + } + return count; + } + + +} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/FeatureCache.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/FeatureCache.java new file mode 100644 index 0000000000000000000000000000000000000000..b797f2083565afce69e899d372b1bb9965a388fe --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/FeatureCache.java @@ -0,0 +1,329 @@ +package de.hft.stuttgart.citydoctor2.database; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.github.benmanes.caffeine.cache.RemovalCause; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; + + +/** + * A managed cache for top-level CityObjects (Features). This cache is connected to the embedded database and will + * automatically load missing CityObjects from it. This cache is size limited and will evict entries using the + * Window Tiny LFU policy. + *

+ * While this class is not a singleton, it is advised to keep an Instance of this class for the whole lifecycle and + * reset and reuse it instead of creating new Objects, as the initialization is quite heavy and resets the embedded + * database. + *

+ *

+ * Avoid holding long-time strong references to CityObjects returned by the cache, as eviction will sever the + * connection between reference and cache, which will lead to conflicting Object states. + *

+ */ +public class FeatureCache implements CityObjectCache{ + + + private static final Logger logger = LogManager.getLogger(FeatureCache.class); + + private final LoadingCache cache; + private final EmbeddedDatabaseHandler handler; + private final AtomicInteger putsCounter = new AtomicInteger(0); + private CacheState state = CacheState.IDLE; + private final ConcurrentHashMap evictionLocks = new ConcurrentHashMap<>(); + + public FeatureCache() { + handler = new EmbeddedDatabaseHandler(); + cache = Caffeine.newBuilder().maximumSize(3000).removalListener((GmlId key, CityObject value, RemovalCause cause) -> { + if (value != null && cause.wasEvicted() && isFeatureMarshallable(value)){ + handler.marshallCityObject(value); + } + }).build(handler::unmarshallCityObject); + } + + /** + * Checks if the CityObject is currently being checked by a Checker-thread to prevent concurrent modifications by the + * Marshaller on eviction. + * @param co the CityObject + * @return true if the CityObject can be marshalled, false otherwise + */ + private boolean isFeatureMarshallable(CityObject co) { + return switch (state){ + case IDLE, PARSING -> true; + case CHECKING -> ! (evictionLocks.containsValue(co.getGmlId())); + }; + } + + @Override + public void put(CityObject cityObject) { + cache.put(cityObject.getGmlId(), cityObject); + switch (state){ + case IDLE: + break; + case PARSING: + int count = putsCounter.incrementAndGet(); + if (count >= 2500) { + batchMarshall(); + } + break; + case CHECKING: + evictionLocks.remove(Thread.currentThread()); + break; + } + } + + + private void batchMarshall(){ + logger.trace("Setting up batch Marshaller"); + Map cacheContent= new HashMap<>(cache.asMap()); + cache.invalidateAll(); + putsCounter.set(0); + + Thread batcher = new Thread(() -> { + logger.trace("Entered batch Marshaller"); + boolean success = handler.tryMarshallCityObjectMap(cacheContent); + if (!success) { + logger.trace("Batch marshalling in Thread failed, falling back to one-by-one marshalling"); + for (Map.Entry entry : cacheContent.entrySet()) { + handler.marshallCityObject(entry.getValue()); + } + } + logger.trace("Batch marshalling done"); + }); + batcher.start(); + logger.trace("Batch Marshaller started"); + } + + @Override + public CityObject get(GmlId id) { + if (state == CacheState.CHECKING){ + evictionLocks.put(Thread.currentThread(), id); + } + return cache.get(id); + } + + + + @Override + public void replace(GmlId id, CityObject cityObject) { + cache.invalidate(id); + cache.put(cityObject.getGmlId(), cityObject); + } + + @Override + public Stream getStream(List gmlIds) { + return gmlIds.stream().map(this::get); + } + + @Override + public int getTotalFeatureCount() { + return handler.getFeatureCount(); + } + + @Override + public void resetCache(){ + logger.trace("Resetting cache"); + cache.invalidateAll(); + putsCounter.set(0); + handler.setupFeaturesTable(); + } + + @Override + public List getErrorFeatureIds() { + return handler.getIdsOfAllCityObjectsWithErrors(); + + } + + /** + * Synchronizes CityObject states by updating Database with cache content. + */ + public void synchronize(){ + HashMap cacheContent= new HashMap<>(cache.asMap()); + boolean success = handler.tryMarshallCityObjectMap(cacheContent); + if (!success) { + logger.trace("Batch marshalling failed, falling back to one-by-one marshalling"); + for (Map.Entry entry : cacheContent.entrySet()) { + handler.marshallCityObject(entry.getValue()); + } + } + } + + /** + * Signals the cache that parsing is beginning. + */ + private boolean beginParsing(){ + return state.changeState(this, CacheState.PARSING); + } + + /** + * Signals the cache that parsing has finished. + */ + private void finishParsing() { + if (state == CacheState.PARSING && state.changeState(this, CacheState.IDLE)){ + return; + } + throw new IllegalStateException("Cache failed to exit parsing mode"); + } + + /** + * Signals the cache that checking is beginning. + */ + private boolean beginChecking(){ + return state.changeState(this, CacheState.CHECKING); + } + + /** + * Signals the cache that checking has finished. + */ + private void finishChecking() { + if (state == CacheState.CHECKING && state.changeState(this, CacheState.IDLE)){ + return; + } + throw new IllegalStateException("Cache failed to exit checking mode"); + } + + @Override + public AutoCloseable startParsingMode(){ + if (this.beginParsing()){ + return this::finishParsing; + } else throw new IllegalStateException("Cache is not in IDLE state, cannot start parsing mode"); + } + + @Override + public AutoCloseable startCheckingMode(){ + if (this.beginChecking()){ + return this::finishChecking; + } else throw new IllegalStateException("Cache is not in IDLE state, cannot start checking mode"); + } + + protected void setState(CacheState state) { + this.state = state; + } + + public CacheState getState() { + return state; + } + + public enum CacheState { + IDLE { + @Override + protected boolean changeState(FeatureCache cache, CacheState nextState) { + if (cache.getState() != this){ + logger.debug("FeatureCache invoked changeState() of IDLE state while cache state is {}", cache.getState()); + return false; + } + this.onExit(cache); + cache.setState(nextState); + nextState.onEntry(cache); + return true; + } + + @Override + public void onEntry(FeatureCache cache) { + logger.trace("FeatureCache: Entering IDLE state"); + // Idle state does nothing on entry + } + + @Override + protected void onExit(FeatureCache cache) { + logger.trace("FeatureCache: Leaving IDLE state"); + // Idle state does nothing on exit + } + + }, PARSING { + @Override + protected boolean changeState(FeatureCache cache, CacheState nextState) { + if (cache.getState() != this){ + logger.debug("FeatureCache invoked changeState() of PARSING state while cache state is {}", cache.getState()); + return false; + } + boolean success = false; + switch (nextState){ + case IDLE: + this.onExit(cache); + cache.setState(CacheState.IDLE); + success = true; + break; + case PARSING: + logger.debug("Tried to set cache to PARSING state while already parsing"); + break; + case CHECKING: + logger.debug("Tried to set cache to CHECKING state while parsing"); + break; + } + return success; + } + + @Override + public void onEntry(FeatureCache cache) { + logger.trace("FeatureCache: Entering PARSING state"); + cache.resetCache(); + } + + @Override + protected void onExit(FeatureCache cache) { + logger.trace("FeatureCache: Leaving PARSING state"); + cache.synchronize(); + } + + }, CHECKING { + @Override + protected boolean changeState(FeatureCache cache, CacheState nextState) { + if (cache.getState() != this){ + logger.debug("FeatureCache invoked changeState() of CHECKING state while cache state is {}", cache.getState()); + return false; + } + boolean success = false; + switch (nextState){ + case IDLE: + this.onExit(cache); + cache.setState(CacheState.IDLE); + success = true; + break; + case PARSING: + logger.debug("Tried to set cache to PARSING state while checking"); + break; + case CHECKING: + logger.debug("Tried to set cache to CHECKING state while already checking"); + break; + } + return success; + } + + @Override + public void onEntry(FeatureCache cache) { + logger.trace("FeatureCache: Entering CHECKING state"); + + } + + @Override + protected void onExit(FeatureCache cache) { + logger.trace("FeatureCache: Leaving CHECKING state"); + cache.synchronize(); + } + + + }; + + /** + * Signals the statemachine to change the state of the FeatureCache. Returns true if the state successfully + * changed, false otherwise with the FeatureCache remaining in its current state. + * @param cache the FeatureCache instance + * @param nextState the requested next state + * @return true if the cache successfully changed state, false otherwise + */ + protected abstract boolean changeState(FeatureCache cache, CacheState nextState); + protected abstract void onEntry(FeatureCache cache); + protected abstract void onExit(FeatureCache cache); + } +} + diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/UnconnectedCache.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/UnconnectedCache.java new file mode 100644 index 0000000000000000000000000000000000000000..8033e63461e8719c59b4946da2513db40bf9ba35 --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/UnconnectedCache.java @@ -0,0 +1,85 @@ +package de.hft.stuttgart.citydoctor2.database; + +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +/** + * An adapter implementation for CityObjectCache, wrapping the Interface around a simple HashMap. + *

+ * This class is intended to allow parsing or checking {@link CityDoctorModel CityDoctorModels} in specific cases where the model + * must not use the {@link FeatureCache}, like resolving of {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject LibraryObject} + * files or mocking of the Interface in unit tests. + * + */ +public class UnconnectedCache implements CityObjectCache{ + + private final Map cache; + private boolean idle = true; + + public UnconnectedCache() { + cache = new HashMap<>(); + } + + @Override + public void put(CityObject cityObject) { + cache.put(cityObject.getGmlId(), cityObject); + } + + @Override + public CityObject get(GmlId id) { + return cache.get(id); + } + + @Override + public void replace(GmlId id, CityObject cityObject) { + cache.put(id, cityObject); + } + + @Override + public Stream getStream(List ids) { + return cache.values().stream().filter(c -> ids.contains(c.getGmlId())); + } + + @Override + public int getTotalFeatureCount() { + return cache.size(); + } + + public void resetCache(){ + cache.clear(); + } + + @Override + public List getErrorFeatureIds() { + List errorFeatureIds = new ArrayList<>(); + cache.forEach((gmlId, cityObject) ->{ + if (cityObject.containsAnyError()){ + errorFeatureIds.add(cityObject.getGmlId()); + } + }); + return errorFeatureIds; + } + + @Override + public AutoCloseable startParsingMode() { + if (idle){ + idle = false; + return ()-> idle=true; + } else throw new IllegalStateException("Cache is not idle, could not start parsing mode"); + } + + @Override + public AutoCloseable startCheckingMode() { + if (idle){ + idle = false; + return ()-> idle=true; + } else throw new IllegalStateException("Cache is not idle, could not start checking mode"); + } +} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java index 9fa5066c6b7917a93c983831d4a05b99df03c0c3..c3dd9d63d95482e9e1bf942bc60755c036988079 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurface.java @@ -40,7 +40,7 @@ public class BoundarySurface extends CityObject { @Serial private static final long serialVersionUID = 8793865135393496408L; - private SurfaceFeatureType featureType; + private BoundarySurfaceType type; private final List openings = new ArrayList<>(2); @@ -49,18 +49,14 @@ public class BoundarySurface extends CityObject { private AbstractThematicSurface gmlObject; public BoundarySurface(AbstractThematicSurface aco) { - this(SurfaceFeatureType.BUILDING, BoundarySurfaceType.UNDEFINED, aco); + this(BoundarySurfaceType.UNDEFINED, aco); } - public BoundarySurface(SurfaceFeatureType featureType, BoundarySurfaceType type, AbstractThematicSurface aco) { - this.featureType = featureType; + public BoundarySurface(BoundarySurfaceType type, AbstractThematicSurface aco) { this.type = type; gmlObject = aco; } - public void setFeatureType(SurfaceFeatureType featureType) { - this.featureType = featureType; - } public void setType(BoundarySurfaceType type) { this.type = type; @@ -70,9 +66,6 @@ public class BoundarySurface extends CityObject { this.gmlObject = gmlObject; } - public SurfaceFeatureType getSurfaceFeatureType() { - return featureType; - } public BoundarySurfaceType getType() { return type; diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java index f2d535fefc886a4b077859379718bf1a0323a35c..bf5ac32651cdd9f0f4c048e8dc5e6764feed8e04 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java @@ -20,9 +20,11 @@ package de.hft.stuttgart.citydoctor2.datastructure; import de.hft.stuttgart.citydoctor2.math.Vector3d; import de.hft.stuttgart.citydoctor2.utils.BoundingBoxCalculator; +import de.hft.stuttgart.citydoctor2.utils.visitors.MinMaxExtentVisitor; import java.util.Collection; import java.util.List; +import java.util.Locale; /** * An axis aligned bounding box represented by its two corners @@ -47,6 +49,12 @@ public class BoundingBox { return BoundingBoxCalculator.calculateBoundingBoxFromPoints(points); } + public static BoundingBox of(CityObject co) { + MinMaxExtentVisitor mima = new MinMaxExtentVisitor(); + co.accept(mima); + return BoundingBox.of(mima.getMinMaxExtent()); + } + /** * Creates an axis aligned bounding box of the whole model. * @@ -161,4 +169,45 @@ public class BoundingBox { public double getDiagonalLength() { return bbox[1].getDistance(bbox[0]); } + + /** + * Returns whether this BoundinBox is undefined, meaning that one or all corners are infinite. + * @return True if the BoundingBox is undefined, false otherwise + */ + public boolean isUndefined(){ + double x1 = bbox[0].getX(); + double y1 = bbox[0].getY(); + double x2 = bbox[1].getX(); + double y2 = bbox[1].getY(); + return (Double.isInfinite(x1) || Double.isInfinite(y1) || Double.isInfinite(x2) || Double.isInfinite(y2)); + } + + /** + * Returns an axis-aligned 2D polygon projection of this bbox as a WKT String. + *

+ * An undefined bbox will return an empty polygon. + * @return The 2D polygon WKT for this bbox + */ + public String to2DWkt() { + if (this.isUndefined()){ + return "POLYGON EMPTY"; + } + double x1 = bbox[0].getX(); + double y1 = bbox[0].getY(); + double x2 = bbox[1].getX(); + double y2 = bbox[1].getY(); + + double minX = Math.min(x1, x2); + double minY = Math.min(y1, y2); + double maxX = Math.max(x1, x2); + double maxY = Math.max(y1, y2); + + return String.format(Locale.ROOT,"POLYGON((%.3f %.3f, %.3f %.3f, %.3f %.3f, %.3f %.3f, %.3f %.3f))", + minX, minY, + maxX, minY, + maxX, maxY, + minX, maxY, + minX, minY + ); + } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java index 0f475c44dc83d073c4d610538f9bf5db47932942..ba0be98f219adfe4c55ff770fa05c6bdca1a70f9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java @@ -21,6 +21,7 @@ package de.hft.stuttgart.citydoctor2.datastructure; import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor; import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckableVisitor; +import de.hft.stuttgart.citydoctor2.database.CityObjectCache; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.writer.CityGMLWriterUtils; @@ -46,15 +47,15 @@ import java.util.stream.Stream; public class CityDoctorModel { private static final String COULD_NOT_FIND_FEATURE = "Could not find feature: "; - private final List buildings; - private final List vegetation; - private final List bridges; - private final List cityfurniture; - private final List genericObjects; - private final List land; - private final List roads; - private final List tunnels; - private final List water; + private final List buildings; + private final List vegetation; + private final List bridges; + private final List cityfurniture; + private final List genericObjects; + private final List land; + private final List roads; + private final List tunnels; + private final List water; private CityModel cModel; private final ParserConfiguration config; private final String fileName; @@ -63,11 +64,15 @@ public class CityDoctorModel { private boolean isValidated = false; private ValidationPlan plan; private CityGMLVersion cityGMLVersion; + private final CityObjectCache cache; - public CityDoctorModel(ParserConfiguration config, File file) { + public CityDoctorModel(ParserConfiguration config, File file, CityObjectCache cache) { if (config == null) { throw new IllegalArgumentException("Parser configuration may not be null"); } + if( file == null ) { + throw new IllegalArgumentException("File may not be null"); + } this.fileName = file.getName(); this.config = config; this.file = file; @@ -81,6 +86,7 @@ public class CityDoctorModel { cityfurniture = new ArrayList<>(); genericObjects = new ArrayList<>(); globalErrors = new ArrayList<>(); + this.cache = cache; } public boolean isValidated() { @@ -118,20 +124,59 @@ public class CityDoctorModel { } public Stream createFeatureStream() { - return Stream.of(buildings.stream(), vegetation.stream(), bridges.stream(), land.stream(), roads.stream(), - tunnels.stream(), water.stream(), cityfurniture.stream(), genericObjects.stream()).flatMap(co -> co); + return Stream.of(getBuildings(), getVegetation(), getBridges(), getLand(), getTransportation(), + getTunnels(), getWater(), getCityFurniture(), getOtherCityObjects()).flatMap(co -> co); + } + + public List getFeatureIds() { + List featureIds = new ArrayList<>(); + featureIds.addAll(buildings); + featureIds.addAll(vegetation); + featureIds.addAll(bridges); + featureIds.addAll(land); + featureIds.addAll(roads); + featureIds.addAll(tunnels); + featureIds.addAll(water); + featureIds.addAll(cityfurniture); + featureIds.addAll(genericObjects); + return featureIds; + + } + + public boolean containsGmlId(String id) { + if (id == null) { + return false; + } + GmlId gmlId = new GmlId(id); + if (buildings.contains(gmlId)) { + return true; + } + if (vegetation.contains(gmlId)) { + return true; + } + if (bridges.contains(gmlId)) { + return true; + } + if (land.contains(gmlId)) { + return true; + } + if (roads.contains(gmlId)) { + return true; + } + if (tunnels.contains(gmlId)) { + return true; + } + if (water.contains(gmlId)) { + return true; + } + if (cityfurniture.contains(gmlId)) { + return true; + } + return genericObjects.contains(gmlId); } public void accept(CheckableVisitor visitor) { - buildings.forEach(co -> co.accept(visitor)); - vegetation.forEach(co -> co.accept(visitor)); - bridges.forEach(co -> co.accept(visitor)); - land.forEach(co -> co.accept(visitor)); - roads.forEach(co -> co.accept(visitor)); - tunnels.forEach(co -> co.accept(visitor)); - water.forEach(co -> co.accept(visitor)); - cityfurniture.forEach(co -> co.accept(visitor)); - genericObjects.forEach(co -> co.accept(visitor)); + createFeatureStream().forEach(cityObject -> cityObject.accept(visitor)); } public void saveAs(String file, boolean saveQualityAde) throws CityDoctorWriteException { @@ -149,6 +194,7 @@ public class CityDoctorModel { } } + private void exportAsGML(String file) throws CityDoctorWriteException { CityGMLWriterUtils.writeCityModel(file, this); } @@ -228,106 +274,201 @@ public class CityDoctorModel { public Set collectErrors() { List errors = new ArrayList<>(); - collectErrorsFromList(errors, buildings); - collectErrorsFromList(errors, vegetation); - collectErrorsFromList(errors, bridges); - collectErrorsFromList(errors, land); - collectErrorsFromList(errors, roads); - collectErrorsFromList(errors, tunnels); - collectErrorsFromList(errors, water); - collectErrorsFromList(errors, cityfurniture); - collectErrorsFromList(errors, genericObjects); + createFeatureStream().forEach(cityObject -> cityObject.collectErrors(errors)); return new HashSet<>(errors); } - private void collectErrorsFromList(List errors, List cos) { - for (CityObject co : cos) { - co.collectContainedErrors(errors); - } - } public String getFileName() { return fileName; } - public void addBridge(BridgeObject coBridge) { - bridges.add(coBridge); - } public void addBuilding(Building coBuilding) { - buildings.add(coBuilding); + buildings.add(coBuilding.getGmlId()); + cache.put(coBuilding); + } + + public void removeFeature(GmlId id){ + buildings.remove(id); + vegetation.remove(id); + bridges.remove(id); + land.remove(id); + roads.remove(id); + tunnels.remove(id); + water.remove(id); + cityfurniture.remove(id); + genericObjects.remove(id); + } + + public Stream getBuildings() { + return buildings.stream().map(co -> (Building) cache.get(co)); } - public List getBuildings() { + public List getBuildingIds() { return buildings; } - public List getBridges() { + public int getBuildingCount(){ + return buildings.size(); + } + + public void addBridge(BridgeObject coBridge) { + bridges.add(coBridge.getGmlId()); + cache.put(coBridge); + } + + public Stream getBridges() { + return bridges.stream().map(co -> (BridgeObject) cache.get(co)); + } + + public List getBridgeIds() { return bridges; } - public List getCityFurniture() { - return cityfurniture; + public int getBridgeCount(){ + return bridges.size(); } public void addCityFurniture(CityFurniture coFurniture) { - cityfurniture.add(coFurniture); + cityfurniture.add(coFurniture.getGmlId()); + cache.put(coFurniture); + } + + public Stream getCityFurniture() { + return cityfurniture.stream().map(co -> (CityFurniture) cache.get(co)); + } + + public List getCityFurnitureIds() { + return cityfurniture; + } + + public int getCityFurnitureCount(){ + return cityfurniture.size(); + } + + public void addOtherCityObject(CityObject otherCityObject) { + genericObjects.add(otherCityObject.getGmlId()); + cache.put(otherCityObject); + } + + public Stream getOtherCityObjects() { + return genericObjects.stream().map(cache::get); } - public List getGenericCityObjects() { + public List getOtherCityObjectsIds() { return genericObjects; } - public void addGenericCityObject(GenericCityObject coGenericCityObject) { - genericObjects.add(coGenericCityObject); + public int getOtherCityObjectsCount(){ + return genericObjects.size(); } - public void setCityModel(CityModel cModel) { - this.cModel = cModel; + public void addTransportation(TransportationObject to) { + roads.add(to.getGmlId()); + cache.put(to); } - public CityModel getCityModel() { - return cModel; + public Stream getTransportation() { + return roads.stream().map(co -> (TransportationObject) cache.get(co)); } - public List getTransportation() { + public List getTransportationIds() { return roads; } - public List getTunnels() { - return tunnels; + public int getTransportationCount(){ + return roads.size(); } - public List getWater() { - return water; + public void addTunnel(Tunnel tunnel) { + tunnels.add(tunnel.getGmlId()); + cache.put(tunnel); } - public List getLand() { - return land; + public Stream getTunnels() { + return tunnels.stream().map(co -> (Tunnel) cache.get(co)); } - public List getVegetation() { - return vegetation; + public List getTunnelIds() { + return tunnels; + } + + public int getTunnelCount(){ + return tunnels.size(); } public void addWater(WaterObject wo) { - water.add(wo); + water.add(wo.getGmlId()); + cache.put(wo); + } + + public Stream getWater() { + return water.stream().map(co -> (WaterObject) cache.get(co)); + } + + public List getWaterIds() { + return water; + } + + public int getWaterCount(){ + return water.size(); } public void addLand(LandObject lo) { - land.add(lo); + land.add(lo.getGmlId()); + cache.put(lo); + } + + public void addRelief(ReliefObject relief) { + land.add(relief.getGmlId()); + cache.put(relief); + } + + public void addTin(TinObject tin) { + land.add(tin.getGmlId()); + cache.put(tin); + } + + public Stream getLand() { + return land.stream().map(cache::get); + } + + public List getLandIds() { + return land; + } + + public int getLandCount(){ + return land.size(); } public void addVegetation(Vegetation veg) { - vegetation.add(veg); + vegetation.add(veg.getGmlId()); + cache.put(veg); } - public void addTransportation(TransportationObject to) { - roads.add(to); + public Stream getVegetation() { + return vegetation.stream().map(co -> (Vegetation) cache.get(co)); } - public void addTunnel(Tunnel tunnel) { - tunnels.add(tunnel); + public List getVegetationIds() { + return vegetation; + } + + public int getVegetationCount(){ + return vegetation.size(); + } + + public void setCityModel(CityModel cModel) { + this.cModel = cModel; + } + + public CityModel getCityModel() { + return cModel; + } + + public CityObjectCache getCache(){ + return cache; } public int getNumberOfFeatures() { @@ -362,100 +503,109 @@ public class CityDoctorModel { } private void replaceWaterObject(CityObject currentFeature, CityObject nextFeature) { - int index = water.indexOf(currentFeature); + int index = water.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in water objects"); } - water.set(index, (WaterObject) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + water.set(index, nextFeature.getGmlId()); } private void replaceLandObject(CityObject currentFeature, CityObject nextFeature) { - int index = land.indexOf(currentFeature); + int index = land.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in land objects"); } - land.set(index, nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + land.set(index, nextFeature.getGmlId()); } private void replaceVegetation(CityObject currentFeature, CityObject nextFeature) { - int index = vegetation.indexOf(currentFeature); + int index = vegetation.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in vegetation"); } - vegetation.set(index, (Vegetation) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + vegetation.set(index, nextFeature.getGmlId()); } private void replaceCityFurniture(CityObject currentFeature, CityObject nextFeature) { - int index = cityfurniture.indexOf(currentFeature); + int index = cityfurniture.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in vegetation"); } - cityfurniture.set(index, (CityFurniture) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + cityfurniture.set(index, nextFeature.getGmlId()); } private void replaceGenericCityObject(CityObject currentFeature, CityObject nextFeature) { - int index = genericObjects.indexOf(currentFeature); + int index = genericObjects.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in generic city objects"); } - genericObjects.set(index, (GenericCityObject) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + genericObjects.set(index, nextFeature.getGmlId()); } private void replaceTransportationObject(CityObject currentFeature, CityObject nextFeature) { - int index = roads.indexOf(currentFeature); + int index = roads.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in transportation objects"); } - roads.set(index, (TransportationObject) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + roads.set(index, nextFeature.getGmlId()); } private void replaceTunnel(CityObject currentFeature, CityObject nextFeature) { - int index = tunnels.indexOf(currentFeature); + int index = tunnels.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in tunnels"); } - tunnels.set(index, (Tunnel) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + tunnels.set(index, nextFeature.getGmlId()); } private void replaceBridge(CityObject currentFeature, CityObject nextFeature) { - int index = bridges.indexOf(currentFeature); + int index = bridges.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in bridges"); } - bridges.set(index, (BridgeObject) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + bridges.set(index, nextFeature.getGmlId()); } private void replaceBuilding(CityObject currentFeature, CityObject nextFeature) { - int index = buildings.indexOf(currentFeature); + int index = buildings.indexOf(currentFeature.getGmlId()); if (index == -1) { throw new IllegalStateException(COULD_NOT_FIND_FEATURE + currentFeature + " in buildings"); } - buildings.set(index, (Building) nextFeature); + cache.replace(currentFeature.getGmlId(), nextFeature); + buildings.set(index, nextFeature.getGmlId()); } public void addCityObject(CityObject co) { if (co instanceof Building b) { - buildings.add(b); + buildings.add(b.getGmlId()); } else if (co instanceof BridgeObject bo) { - bridges.add(bo); + bridges.add(bo.getGmlId()); } else if (co instanceof TransportationObject to) { - roads.add(to); + roads.add(to.getGmlId()); } else if (co instanceof Tunnel tu) { - tunnels.add(tu); + tunnels.add(tu.getGmlId()); } else if (co instanceof Vegetation veg) { - vegetation.add(veg); + vegetation.add(veg.getGmlId()); } else if (co instanceof LandObject lo) { - land.add(lo); + land.add(lo.getGmlId()); } else if (co instanceof WaterObject wo) { - water.add(wo); + water.add(wo.getGmlId()); } else if (co instanceof ReliefObject) { - land.add(co); + land.add(co.getGmlId()); } else if (co instanceof TinObject) { - land.add(co); + land.add(co.getGmlId()); } else if (co instanceof CityFurniture cf) { - cityfurniture.add(cf); + cityfurniture.add(cf.getGmlId()); } else if (co instanceof GenericCityObject gco) { - genericObjects.add(gco); + genericObjects.add(gco.getGmlId()); } } @@ -467,11 +617,4 @@ public class CityDoctorModel { return cityGMLVersion; } - public void addRelief(ReliefObject relief) { - addCityObject(relief); - } - - public void addTin(TinObject tin) { - addCityObject(tin); - } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java index cb49e1e0be23185738391db890f127310de131c0..11a8e687b14ee8ba5a78cb68c0c2374878de7156 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/FeatureType.java @@ -27,5 +27,5 @@ public enum FeatureType { BUILDING, TRANSPORTATION, VEGETATION, BRIDGE, LAND, WATER, BOUNDARY_SURFACE, INSTALLATION, OPENING, BUILDING_PART, BUILDING_SUBDIVISION, BRIDGE_CONSTRUCTION_ELEMENT, BRIDGE_INSTALLATION, ROOM, FURNITURE, CITY_FURNITURE, - GENERIC_CITY_OBJECT, TUNNEL, TUNNEL_PART, TUNNEL_CONSTRUCTION_ELEMENT, TUNNEL_INSTALLATION, + OTHER_CITY_OBJECT, TUNNEL, TUNNEL_PART, TUNNEL_CONSTRUCTION_ELEMENT, TUNNEL_INSTALLATION, } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericAttribute.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericAttribute.java index cd8cec53b61a0742dbe6b5efa581feaacb8bfdbb..835a0fd2b3f21875dfe6d8eeca34c8e6015b9f01 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericAttribute.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericAttribute.java @@ -5,10 +5,16 @@ import org.apache.logging.log4j.Logger; import org.citygml4j.core.model.core.AbstractGenericAttributeProperty; import org.citygml4j.core.model.generics.*; +import java.io.Serial; +import java.io.Serializable; + import java.util.List; -public class GenericAttribute { +public class GenericAttribute implements Serializable { + + @Serial + private static final long serialVersionUID = -4101408947632132328L; private static final Logger logger = LogManager.getLogger(GenericAttribute.class); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericCityObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericCityObject.java index 34a0d022d9975433061979ff8043e724dd38f5b8..a8aa7bfb1a0c89fd3b0e3780400a7d1031d09421 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericCityObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericCityObject.java @@ -111,7 +111,7 @@ public class GenericCityObject extends CityObject { cgmlGos.getDeprecatedProperties().setLod4Geometry(new SolidProperty(solid)); break; default: - throw new IllegalStateException("Cannot add " + geom.getLod() + " solid to buildings"); + throw new IllegalStateException("Cannot add " + geom.getLod() + " solid to generic city object"); } } @Override @@ -121,7 +121,7 @@ public class GenericCityObject extends CityObject { @Override public FeatureType getFeatureType() { - return FeatureType.GENERIC_CITY_OBJECT; + return FeatureType.OTHER_CITY_OBJECT; } public List getBoundarySurfaces() { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java index d7c17240faa18fbbd5a789468956d4ac75983b18..f2c0d41942e725d652ad7e9567285902f0a78d9d 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java @@ -26,6 +26,8 @@ import de.hft.stuttgart.citydoctor2.utils.BoundingBoxCalculator; import de.hft.stuttgart.citydoctor2.utils.SerializablePair; import javafx.scene.paint.Color; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serial; import java.util.*; @@ -53,9 +55,9 @@ public class Geometry extends GmlElement { private CityObject parent; private final List polygons = new ArrayList<>(2); - private List edges; - private Map, Edge> edgeMap; - private List vertices; + private transient List edges; + private transient Map, Edge> edgeMap; + private transient List vertices; private Orientation orientation; public Geometry(GeometryType type, Lod lod, Orientation orientation) { @@ -344,6 +346,12 @@ public class Geometry extends GmlElement { return false; } + @Serial + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + edges = new ArrayList<>(); + edgeMap = new HashMap<>(); + } public void clearMetaData() { if (vertices != null) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ImplicitGeometryHolder.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ImplicitGeometryHolder.java index 6a01fa8426b8657a5a6434eb95423ccf4c1fad60..8285eb93603f0dee513600bb648b20d1e0c9f80b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ImplicitGeometryHolder.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ImplicitGeometryHolder.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import de.hft.stuttgart.citydoctor2.check.CheckableVisitor; +import de.hft.stuttgart.citydoctor2.database.CityObjectCache; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.citygml4j.core.model.core.ImplicitGeometry; @@ -23,6 +24,10 @@ public class ImplicitGeometryHolder extends Geometry { private static final long serialVersionUID = -8938931081577196349L; private static final Logger logger = LogManager.getLogger(ImplicitGeometryHolder.class); + public enum PrototypeGeometryType { + LIBRARY_OBJECT, RELATIVE_GEOMETRY + } + private ImplicitGeometry cgmlImplicitGeometry = null; private static ConcurrentHashMap deferredRelGeomObjects = new ConcurrentHashMap<>(); @@ -51,8 +56,11 @@ public class ImplicitGeometryHolder extends Geometry { return igh; } - public static void resolveDeferredObjects() { + public static void resolveDeferredObjects(CityObjectCache cache) { Set missingGeoms = new HashSet<>(); + if(!deferredRelGeomObjects.isEmpty()) { + logger.info("Resolving deferred relative geometries"); + } for (ImplicitGeometryHolder key : deferredRelGeomObjects.keySet()) { ImplicitGeometry ig = deferredRelGeomObjects.get(key); String hrefId = ig.getRelativeGeometry().getHref(); @@ -61,7 +69,7 @@ public class ImplicitGeometryHolder extends Geometry { RelativeGeometry relGeom = RelativeGeometry.of(gmlId); if (relGeom != null) { ImplicitGeometryHolder igh = new ImplicitGeometryHolder(ig, relGeom); - CityObject parent = key.getParent(); + CityObject parent = cache.get(key.getParent().getGmlId()); parent.removeGeometry(igh.getLod(), igh.getType()); parent.addGeometry(igh); } else { @@ -72,6 +80,9 @@ public class ImplicitGeometryHolder extends Geometry { logger.warn("RelativeGeometries of the following gmlIDs could not be resolved: {}", missingGeoms); } deferredRelGeomObjects.clear(); + if (logger.isDebugEnabled()) { + logger.debug("Resolving HRef geometries finished"); + } } private ImplicitGeometryHolder(Lod lod) { @@ -94,6 +105,30 @@ public class ImplicitGeometryHolder extends Geometry { return type; } + /** + * Resets the Object maps of {@link RelativeGeometry} and {@link LibraryObject} to prevent memory and data leaks + */ + public static void resetObjectMaps() { + RelativeGeometry.resetObjectMap(); + LibraryObject.resetObjectMap(); + } + + /** + * Prepares the prototype geometries for checking and sets a lock to prevent clearing of metadata + */ + public static void preparePrototypeGeometriesForChecking(){ + RelativeGeometry.preparePrototypeGeometriesForChecking(); + LibraryObject.preparePrototypeGeometriesForChecking(); + } + + /** + * Clears metadata creating for checking of prototype geometries and releases the metadata lock + */ + public static void clearMetaDataOfPrototypeGeometries(){ + RelativeGeometry.clearMetaDataOfPrototypeGeometries(); + LibraryObject.clearMetaDataOfPrototypeGeometries(); + } + @Override public void accept(CheckableVisitor c) { prototypeGeometry.accept(c); @@ -104,8 +139,5 @@ public class ImplicitGeometryHolder extends Geometry { return prototypeGeometry.isValidated(); } - public enum PrototypeGeometryType { - LIBRARY_OBJECT, RELATIVE_GEOMETRY - } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LibraryObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LibraryObject.java index f757da769a1b138b12fed1a530cc3f0d1f3b6934..557cd3ef4fd52841d05c45c37062a0eb32778b64 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LibraryObject.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LibraryObject.java @@ -4,7 +4,7 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry; +import de.hft.stuttgart.citydoctor2.utils.Localization; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,8 +26,8 @@ public class LibraryObject extends Geometry { private static final Logger logger = LogManager.getLogger(LibraryObject.class); @Serial private static final long serialVersionUID = -50293435187454911L; - - private static Map libraryObjects = new ConcurrentHashMap<>(); + private static boolean metadataLocked = false; + private static final Map libraryObjects = new ConcurrentHashMap<>(); public static LibraryObject of(Path path, ParserConfiguration config) { if (libraryObjects.containsKey(path.toString())) { @@ -44,22 +44,6 @@ public class LibraryObject extends Geometry { return libOb; } - public static LibraryObject of(CityGmlZipEntry entry, ParserConfiguration config) { - String fileName = entry.getEntrySubPath(); - if (libraryObjects.containsKey(fileName)){ - return libraryObjects.get(fileName); - } - Geometry protoGeom = parseZipEntry(entry, config); - if (protoGeom == null) { - return null; - } - LibraryObject libOb = new LibraryObject(protoGeom.getType(), protoGeom.getLod(), protoGeom.getOrientation()); - protoGeom.getPolygons().forEach(libOb::addPolygon); - libOb.updateEdgesAndVertices(); - libraryObjects.put(fileName, libOb); - return libOb; - } - private LibraryObject(GeometryType type, Lod lod, Orientation orientation) { super(type, lod, orientation); } @@ -69,31 +53,15 @@ public class LibraryObject extends Geometry { Geometry geo = null; if (Files.exists(path)) { try { - geo = getProtoGeometry(CityGmlParser.parseCityGmlFileSilently(path.toString(), config)); + geo = getProtoGeometry(CityGmlParser.nestedCityGmlFileParse(path.toString(), config)); } catch (CityGmlParseException e) { - logger.error(String.format( - "Encountered an error while parsing library object %s", path)); + logger.error(Localization.getText("LibraryObject.parsingError"), path); logger.error(e.getStackTrace()); } catch (InvalidGmlFileException e) { logger.error(e.getStackTrace()); } } else { - logger.error(String.format("Implicit geometry references non-existing library object file %s.", path)); - } - return geo; - } - - private static Geometry parseZipEntry(CityGmlZipEntry entry, ParserConfiguration config) { - Geometry geo = null; - try { - entry.loadEntry(config); - geo = getProtoGeometry(entry.getModel()); - } catch (InvalidGmlFileException e) { - logger.error(e.getStackTrace()); - } catch (CityGmlParseException e) { - logger.error(String.format( - "Encountered an error while parsing library object %s", entry.getEntrySubPath())); - logger.error(e.getStackTrace()); + logger.error(Localization.getText("LibraryObject.fileMissing"), path); } return geo; } @@ -111,4 +79,33 @@ public class LibraryObject extends Geometry { return objects.get(0).getHighestLodGeometry(); } + + public static void resetObjectMap() { + libraryObjects.clear(); + } + + public static void preparePrototypeGeometriesForChecking() { + libraryObjects.values().forEach(LibraryObject::updateEdgesAndVertices); + metadataLocked = true; + } + + public static void clearMetaDataOfPrototypeGeometries() { + metadataLocked = false; + libraryObjects.values().forEach(LibraryObject::clearMetaData); + } + + @Override + public void updateEdgesAndVertices(){ + if (!metadataLocked) { + super.updateEdgesAndVertices(); + } + } + + @Override + public void clearMetaData(){ + if (!metadataLocked) { + super.clearMetaData(); + } + } + } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java index d4d1f20cd48dd7c1ba84bda432431b95d4688004..b59ab14abbeb135cf703876425eefd163381a8c5 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java @@ -44,13 +44,11 @@ public class Opening extends CityObject { private BoundarySurface partOf; private OpeningType type; - private SurfaceFeatureType featureType; private AbstractFillingSurface ao; - public Opening(OpeningType type, SurfaceFeatureType featureType, BoundarySurface partOf, + public Opening(OpeningType type, BoundarySurface partOf, AbstractFillingSurface ao) { - this.featureType = featureType; this.partOf = partOf; this.type = type; this.ao = ao; @@ -92,11 +90,6 @@ public class Opening extends CityObject { } } - - public SurfaceFeatureType getSurfaceFeatureType() { - return featureType; - } - public BoundarySurface getPartOf() { return partOf; } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/OtherConstructionObject.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/OtherConstructionObject.java new file mode 100644 index 0000000000000000000000000000000000000000..d29145d509a607548caf34a802286ce345c4c1e0 --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/OtherConstructionObject.java @@ -0,0 +1,142 @@ +package de.hft.stuttgart.citydoctor2.datastructure; + +import de.hft.stuttgart.citydoctor2.check.CheckableVisitor; +import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; +import de.hft.stuttgart.citydoctor2.utils.CityGmlUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.citygml4j.core.model.construction.OtherConstruction; +import org.citygml4j.core.model.core.AbstractCityObject; +import org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty; +import org.citygml4j.core.util.geometry.GeometryFactory; +import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface; +import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty; +import org.xmlobjects.gml.model.geometry.primitives.Solid; +import org.xmlobjects.gml.model.geometry.primitives.SolidProperty; + +import java.io.Serial; +import java.util.ArrayList; +import java.util.List; + +public class OtherConstructionObject extends CityObject{ + + @Serial + private static final long serialVersionUID = -3885206364978761701L; + + private static final Logger logger = LogManager.getLogger(OtherConstructionObject.class); + + private final List boundarySurfaceList = new ArrayList<>(); + private OtherConstruction gmlObject; + + @Override + public void accept(CheckableVisitor c) { + super.accept(c); + if (c.canExecute(this)) { + c.check(this); + } + for (BoundarySurface bs : boundarySurfaceList) { + bs.accept(c); + } + } + + public void setGmlObject(OtherConstruction gmlObject) { + this.gmlObject = gmlObject; + } + + @Override + public void rebuildGeometries(GeometryFactory factory, ParserConfiguration config) { + for (Geometry geom : getGeometries()) { + if (geom instanceof ImplicitGeometryHolder) { + continue; + } + if (geom.getType() == GeometryType.MULTI_SURFACE) { + MultiSurface ms = CityGmlUtils.createMultiSurface(geom, factory, config); + setMultiSurfaceAccordingToLod(geom, ms); + } else { + Solid solid = CityGmlUtils.createSolid(geom, factory, config); + setSolidAccordingToLod(geom, solid); + } + } + removeEmptyBoundarySurfaces(); + } + + private void removeEmptyBoundarySurfaces() { + for (BoundarySurface bs : boundarySurfaceList) { + if (bs.getGeometries().isEmpty()) { + for (AbstractSpaceBoundaryProperty bsp : gmlObject.getBoundaries()) { + if (bsp.getObject() != null && bsp.getObject() == bs.getGmlObject()) { + logger.warn("Found empty boundary surface: {}, removing from feature", bs.getGmlId()); + gmlObject.getBoundaries().remove(bsp); + break; + } + } + } + } + } + + private void setMultiSurfaceAccordingToLod(Geometry geom, MultiSurface ms) { + switch (geom.getLod()) { + case LOD0: + gmlObject.setLod0MultiSurface(new MultiSurfaceProperty(ms)); + break; + case LOD2: + gmlObject.setLod2MultiSurface(new MultiSurfaceProperty(ms)); + break; + case LOD3: + gmlObject.setLod3MultiSurface(new MultiSurfaceProperty(ms)); + break; + default: + throw new IllegalStateException("Cannot add " + geom.getLod() + " multi surface to other construction object"); + } + } + + private void setSolidAccordingToLod(Geometry geom, Solid solid) { + switch (geom.getLod()) { + case LOD1: + gmlObject.setLod1Solid(new SolidProperty(solid)); + break; + case LOD2: + gmlObject.setLod2Solid(new SolidProperty(solid)); + break; + case LOD3: + gmlObject.setLod3Solid(new SolidProperty(solid)); + break; + default: + throw new IllegalStateException("Cannot add " + geom.getLod() + " solid to other construction object"); + } + } + + @Override + public OtherConstruction getGmlObject() { + return gmlObject; + } + + @Override + public void unsetGmlGeometries() { + gmlObject.setLod0MultiSurface(null); + gmlObject.setLod2MultiSurface(null); + gmlObject.setLod3MultiSurface(null); + gmlObject.setLod1Solid(null); + gmlObject.setLod2Solid(null); + gmlObject.setLod3Solid(null); + } + + @Override + public CityObject getTopLevelCityObject() { + return this; + } + + @Override + public FeatureType getFeatureType() { + return FeatureType.OTHER_CITY_OBJECT; + } + + public void addBoundarySurface(BoundarySurface bs) { + boundarySurfaceList.add(bs); + bs.setParent(this); + } + + public List getBoundarySurfaces() { + return boundarySurfaceList; + } +} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/RelativeGeometry.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/RelativeGeometry.java index 48f8ccd4d258f44998d697c3276f82cb4e299a45..489fa054857e4552ca991a2499a7eec29266354b 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/RelativeGeometry.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/RelativeGeometry.java @@ -15,6 +15,7 @@ public class RelativeGeometry extends Geometry { private static final long serialVersionUID = -686112245455298977L; private static final Map relativeGeometries = new ConcurrentHashMap<>(); + private static boolean metadataLocked = false; public static RelativeGeometry of(GmlId gmlId, Geometry geom) { if (relativeGeometries.containsKey(gmlId)) { @@ -34,4 +35,32 @@ public class RelativeGeometry extends Geometry { private RelativeGeometry(GeometryType type, Lod lod, Orientation orientation) { super(type, lod, orientation); } + + public static void resetObjectMap() { + relativeGeometries.clear(); + } + + public static void preparePrototypeGeometriesForChecking() { + relativeGeometries.values().forEach(RelativeGeometry::updateEdgesAndVertices); + metadataLocked = true; + } + + public static void clearMetaDataOfPrototypeGeometries() { + metadataLocked = false; + relativeGeometries.values().forEach(RelativeGeometry::clearMetaData); + } + + @Override + public void updateEdgesAndVertices(){ + if (!metadataLocked) { + super.updateEdgesAndVertices(); + } + } + + @Override + public void clearMetaData(){ + if (!metadataLocked) { + super.clearMetaData(); + } + } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java index a49aec952b89baf41a61b8e29f7a340ce38ffe28..e42440072b6506f02af1d77a5001c3aa8148dd59 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vertex.java @@ -21,6 +21,8 @@ package de.hft.stuttgart.citydoctor2.datastructure; import de.hft.stuttgart.citydoctor2.math.Vector3d; import de.hft.stuttgart.citydoctor2.utils.SerializablePair; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serial; import java.util.ArrayList; import java.util.HashSet; @@ -37,7 +39,7 @@ public class Vertex extends Vector3d { @Serial private static final long serialVersionUID = -5525361920397934892L; - private List>> adjacentRings = new ArrayList<>(2); + private transient List>> adjacentRings = new ArrayList<>(2); public Vertex(double x, double y, double z) { super(x, y, z); @@ -91,6 +93,12 @@ public class Vertex extends Vector3d { throw new IllegalStateException("Requested adjacent polygons with Geometry not containing this vertex"); } + @Serial + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + clearAdjacentRings(); + } + public Set getAdjacentPolygons(Geometry geom) { return getAdjacentPolygonsWithoutNeighbor(geom); } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java index ade1f2bb0a6edfdf6863b60dae173926e419300e..e27555ca167f86cb172b6346de9db5e3ddf46aa9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java @@ -24,6 +24,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import de.hft.stuttgart.citydoctor2.database.FeatureCache; +import de.hft.stuttgart.citydoctor2.database.UnconnectedCache; +import de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.citygml4j.core.model.CityGMLVersion; @@ -45,6 +48,7 @@ import org.citygml4j.core.model.building.BuildingRoomProperty; import org.citygml4j.core.model.building.BuildingUnit; import org.citygml4j.core.model.building.Storey; import org.citygml4j.core.model.construction.AbstractConstruction; +import org.citygml4j.core.model.construction.OtherConstruction; import org.citygml4j.core.model.core.AbstractCityObject; import org.citygml4j.core.model.core.AbstractFeatureWithLifespan; import org.citygml4j.core.model.core.AbstractGenericAttributeProperty; @@ -157,35 +161,32 @@ import de.hft.stuttgart.citydoctor2.datastructure.WaterObject; import de.hft.stuttgart.citydoctor2.math.graph.KDTree; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.utils.Localization; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry; public class Citygml3FeatureMapper extends ObjectWalker { private static final Logger logger = LogManager.getLogger(Citygml3FeatureMapper.class); + private static FeatureCache featureCache = new FeatureCache(); private final CityDoctorModel model; private final ParserConfiguration config; private final Path directory; - private final CityGmlZipEntry zipEntry; private final double neighborDistance; private Map polygonMap = new HashMap<>(); private Map compositeMap = new HashMap<>(); private List references = new ArrayList<>(); private Map vertexMap = new HashMap<>(); - public Citygml3FeatureMapper(ParserConfiguration config, Path path) { + public Citygml3FeatureMapper(ParserConfiguration config, Path path, boolean unconnected) { this.config = config; this.directory = path.getParent(); - model = new CityDoctorModel(config, path.toFile()); - neighborDistance = 1.8d / Math.pow(10, config.getNumberOfRoundingPlaces()); - zipEntry = null; - } - public Citygml3FeatureMapper(ParserConfiguration config, CityGmlZipEntry entry) { - this.config = config; - this.directory = null; - this.zipEntry = entry; - model = new CityDoctorModel(config, Path.of(entry.getEntrySubPath()).toFile()); + if (unconnected){ + model = new CityDoctorModel(config, path.toFile(), new UnconnectedCache()); + } else { + featureCache.resetCache(); + ImplicitGeometryHolder.resetObjectMaps(); + model = new CityDoctorModel(config, path.toFile(), featureCache); + } neighborDistance = 1.8d / Math.pow(10, config.getNumberOfRoundingPlaces()); } @@ -203,6 +204,32 @@ public class Citygml3FeatureMapper extends ObjectWalker { } + @Override + public void visit(OtherConstruction gmlOc){ + OtherConstructionObject oco = new OtherConstructionObject(); + oco.setGmlObject(gmlOc); + mapAbstractOccupiedSpace(gmlOc, oco, Orientation.OUTWARD); + + SurfaceMapper surfaceMapper = new SurfaceMapper(polygonMap, references, compositeMap, vertexMap, config); + for (AbstractSpaceBoundaryProperty surfaceProp : gmlOc.getBoundaries()) { + if (!surfaceProp.isSetObject()) { + continue; + } + AbstractSpaceBoundary surface = surfaceProp.getObject(); + surface.accept(surfaceMapper); + } + for (BoundarySurface bs : surfaceMapper.getSurfaces()) { + oco.addBoundarySurface(bs); + for (Geometry geom : bs.getGeometries()) { + for (Polygon p : geom.getPolygons()) { + p.setPartOfSurface(bs); + } + } + } + finishCityObjectConstruction(oco); + model.addOtherCityObject(oco); + } + @Override public void visit(org.citygml4j.core.model.cityfurniture.CityFurniture gmlCityFurniture) { CityFurniture cf = new CityFurniture(); @@ -230,7 +257,7 @@ public class Citygml3FeatureMapper extends ObjectWalker { } mapAbstractOccupiedSpace(gos, gco, Orientation.OUTWARD); finishCityObjectConstruction(gco); - model.addGenericCityObject(gco); + model.addOtherCityObject(gco); } @Override @@ -1024,11 +1051,6 @@ public class Citygml3FeatureMapper extends ObjectWalker { if (directory != null){ Path libraryObjectPath = directory.resolve(ig.getLibraryObject()); libObj = LibraryObject.of(libraryObjectPath, config); - } else { - String libraryObjectPath = ig.getLibraryObject(); - Path loPath = zipEntry.resolveLibraryObjectPath(libraryObjectPath); - CityGmlZipEntry libEntry = zipEntry.getArchive().getEntry(loPath.toString()); - libObj = LibraryObject.of(libEntry, config); } if (libObj != null) { igh = new ImplicitGeometryHolder(ig, libObj); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java index c8e8495283789b7a046d17517687595816dda05f..6b3257ad509e783b2bed7b814bc71f77159ab0cd 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/SurfaceMapper.java @@ -54,8 +54,7 @@ public class SurfaceMapper extends ObjectWalker { @Override public void visit(WallSurface wallSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, - wallSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.WALL, wallSurface); handleConstructionSurface(wallSurface, surface); surfaces.add(surface); } @@ -74,11 +73,11 @@ public class SurfaceMapper extends ObjectWalker { private void readAbstractFillingSurface(AbstractFillingSurface afs, BoundarySurface cdSurface) { Opening o; if (afs instanceof DoorSurface ds) { - o = new Opening(OpeningType.DOOR, SurfaceFeatureType.BUILDING, cdSurface, ds); + o = new Opening(OpeningType.DOOR, cdSurface, ds); } else if (afs instanceof WindowSurface ws) { - o = new Opening(OpeningType.WINDOW, SurfaceFeatureType.BUILDING, cdSurface, ws); + o = new Opening(OpeningType.WINDOW, cdSurface, ws); } else { - o = new Opening(OpeningType.UNKNOWN, SurfaceFeatureType.BUILDING, cdSurface, afs); + o = new Opening(OpeningType.UNKNOWN, cdSurface, afs); } cdSurface.addOpening(o); parseAndAddMultiSurface(afs.getLod0MultiSurface(), Lod.LOD0, o); @@ -144,64 +143,56 @@ public class SurfaceMapper extends ObjectWalker { @Override public void visit(FloorSurface floorSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.FLOOR, - floorSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.FLOOR, floorSurface); handleConstructionSurface(floorSurface, surface); surfaces.add(surface); } @Override public void visit(CeilingSurface ceilingSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.CEILING, - ceilingSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.CEILING, ceilingSurface); handleConstructionSurface(ceilingSurface, surface); surfaces.add(surface); } @Override public void visit(GroundSurface groundSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.GROUND, - groundSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.GROUND, groundSurface); handleConstructionSurface(groundSurface, surface); surfaces.add(surface); } @Override public void visit(InteriorWallSurface interiorWallSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.INTERIOR_WALL, - interiorWallSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.INTERIOR_WALL, interiorWallSurface); handleConstructionSurface(interiorWallSurface, surface); surfaces.add(surface); } @Override public void visit(OuterCeilingSurface outerCeilingSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.OUTER_CEILING, - outerCeilingSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.OUTER_CEILING, outerCeilingSurface); handleConstructionSurface(outerCeilingSurface, surface); surfaces.add(surface); } @Override public void visit(OuterFloorSurface outerFloorSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.OUTER_FLOOR, - outerFloorSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.OUTER_FLOOR, outerFloorSurface); handleConstructionSurface(outerFloorSurface, surface); surfaces.add(surface); } @Override public void visit(RoofSurface roofSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.ROOF, - roofSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.ROOF, roofSurface); handleConstructionSurface(roofSurface, surface); surfaces.add(surface); } @Override public void visit(ClosureSurface closureSurface) { - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.CLOSURE, - closureSurface); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.CLOSURE, closureSurface); handleThematicSurface(closureSurface, surface); surfaces.add(surface); } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java index e8ec04fecf32702c7a7c4360eca4e9c7a7fea8d9..d94ab7eecf5a32285c7a3feee955a4d5a5dc7eab 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java @@ -19,7 +19,6 @@ package de.hft.stuttgart.citydoctor2.parser; import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -44,6 +43,7 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; @@ -79,7 +79,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; -import org.xml.sax.SAXParseException; import org.xmlobjects.schema.SchemaHandler; import org.xmlobjects.schema.SchemaHandlerException; import org.xmlobjects.stream.XMLReader; @@ -91,8 +90,6 @@ import de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper; import de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler; import de.hft.stuttgart.citydoctor2.math.Vector3d; import de.hft.stuttgart.citydoctor2.utils.Localization; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile; import de.hft.stuttgart.quality.QualityADEContext; import de.hft.stuttgart.quality.QualityADEModule; @@ -158,33 +155,111 @@ public class CityGmlParser { ADERegistry adeRegistry = ADERegistry.getInstance(); adeRegistry.loadADE(new QualityADEContext()); } catch (CityGMLContextException e) { - logger.fatal("Unable to create citygml4j context", e); + logger.fatal(Localization.getText("CityGmlParser.creating4jContextFailed"), e); throw new IllegalStateException("Unable to create citygml4j context"); } catch (ADEException e) { - logger.fatal("Unable to add ADE plugins to citygml4j", e); + logger.fatal(Localization.getText("CityGmlParser.creatingAdePluginsFailed"), e); throw new IllegalStateException("Unable to add ADE plugins to citygml4j"); } } return context; } - public static CityDoctorModel parseCityGmlFileSilently(String file, ParserConfiguration config) + /** + * Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}. + *

+ * The nested parse uses an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}, which + * is not connected to the database. + *

+ * Nested parsing should only be used for accessing Features in auxiliary, small CityGML files, e.g. parsing of + * {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject LibraryObject} files. + * + * @param filePath String path to the file + * @param config Configuration of the parser + * @return A {@link CityDoctorModel} object with the parsed Features + * @throws CityGmlParseException if parsing of the CityGML-file failed + * @throws InvalidGmlFileException if the GMLValidationHandler found an error + */ + public static CityDoctorModel nestedCityGmlFileParse(String filePath, ParserConfiguration config) throws CityGmlParseException, InvalidGmlFileException { - return parseCityGmlFile(file, config, null, null, false); + return parseCityGmlFile(filePath, config, null, null, false, true); } - public static CityDoctorModel parseCityGmlFile(String file, ParserConfiguration config) + /** + * Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}. + *

+ * Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references + * to {@link CityObject} are to be avoided, to allow for the memory management of the cache. + * + * @param filePath String path to the file + * @param config Configuration of the parser + * @return A {@link CityDoctorModel} object with the parsed Features + * @throws CityGmlParseException if parsing of the CityGML-file failed + * @throws InvalidGmlFileException if the GMLValidationHandler found an error + */ + public static CityDoctorModel parseCityGmlFile(String filePath, ParserConfiguration config) throws CityGmlParseException, InvalidGmlFileException { - return parseCityGmlFile(file, config, null, null, true); + return parseCityGmlFile(filePath, config, null, null); } - public static CityDoctorModel parseCityGmlFile(String file, ParserConfiguration config, ProgressListener l) + + /** + * Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}. + *

+ * Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references + * to {@link CityObject} are to be avoided, to allow for the memory management of the cache. + * + * @param filePath String path to the file + * @param config Configuration of the parser + * @param l Listener hook for tracking of parsing progress + * @return A {@link CityDoctorModel} object with the parsed Features + * @throws CityGmlParseException if parsing of the CityGML-file failed + * @throws InvalidGmlFileException if the GMLValidationHandler found an error + */ + public static CityDoctorModel parseCityGmlFile(String filePath, ParserConfiguration config, ProgressListener l) throws CityGmlParseException, InvalidGmlFileException { - return parseCityGmlFile(file, config, l, null, true); + return parseCityGmlFile(filePath, config, l, null); } + /** + * Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}. + *

+ * Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references + * to {@link CityObject} are to be avoided, to allow for the memory management of the cache. + * + * @param filePath String path to the file + * @param config Configuration of the parser + * @param l Listener hook for tracking of parsing progress + * @param handler Validation handler for GML-file validation + * @return A {@link CityDoctorModel} object with the parsed Features + * @throws CityGmlParseException if parsing of the CityGML-file failed + * @throws InvalidGmlFileException if the GMLValidationHandler found an error + */ public static CityDoctorModel parseCityGmlFile(String filePath, ParserConfiguration config, ProgressListener l, - GMLValidationHandler handler, boolean verbose) throws CityGmlParseException, InvalidGmlFileException { + GMLValidationHandler handler) throws CityGmlParseException, InvalidGmlFileException { + return parseCityGmlFile(filePath, config, l, handler, true, false); + } + + /** + * Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}. + *

+ * Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references + * to {@link CityObject} are to be avoided, to allow for the memory management of the cache. + * + * @param filePath String path to the file + * @param config Configuration of the parser + * @param l Listener hook for tracking of parsing progress + * @param handler Validation handler for GML-file validation + * @param verbose If verbosity is enabled the parser will write info logs to the logger + * @param unconnected If true the parser will use an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache} + * to collect the parsed CityObjects + * @return A {@link CityDoctorModel} object with the parsed Features + * @throws CityGmlParseException if parsing of the CityGML-file failed + * @throws InvalidGmlFileException if the GMLValidationHandler found an error + */ + private static CityDoctorModel parseCityGmlFile(String filePath, ParserConfiguration config, ProgressListener l, + GMLValidationHandler handler, boolean verbose, boolean unconnected) + throws CityGmlParseException, InvalidGmlFileException { CityGMLContext context = getContext(); Path file = Paths.get(filePath); if (config.getValidate()) { @@ -195,14 +270,14 @@ public class CityGmlParser { } try { - parseEpsgCodeFromFile(file, config); + parseEpsgCodeFromFile(file, config, verbose); CityGMLInputFactory in = context.createCityGMLInputFactory() .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false)); try (ObservedInputStream ois = new ObservedInputStream(file.toFile())) { if (l != null) { ois.addListener(l::updateProgress); } - return readAndKeepFeatures(config, file, in, ois, verbose); + return readAndKeepFeatures(config, file, in, ois, verbose, unconnected); } } catch (CityGMLReadException | IOException e) { throw new CityGmlParseException("Failed to read CityGML file", e); @@ -210,118 +285,6 @@ public class CityGmlParser { } - public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config) - throws CityGmlParseException, InvalidGmlFileException, IOException { - return parseCityGmlZipEntry(entry, config, null); - } - - public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l) - throws CityGmlParseException, InvalidGmlFileException, IOException { - CityGMLContext context = getContext(); - - if (config.getValidate()) { - try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) { - List messages = validateStream(entryFile.getInputStream(), context); - if (!messages.isEmpty()) { - throw new InvalidGmlFileException("Invalid GML File. First error: \n" + messages.get(0)); - } - } catch (Exception e) { - throw new CityGmlParseException(e); - } - - } - return decompressAndParseCityGmlEntry(entry, config, l, context); - } - - public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config, CityGMLContext context) - throws CityGmlParseException { - return decompressAndParseCityGmlEntry(entry, config, null, context); - } - - public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l, CityGMLContext context) - throws CityGmlParseException { - - try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) { - BufferedInputStream bis = new BufferedInputStream(entryFile.getInputStream()); - readEpsgCodeFromInputStream(bis, config); - CityGMLInputFactory in = context.createCityGMLInputFactory() - .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false)); - try (ObservedInputStream ois = new ObservedInputStream(bis, bis.available())) { - if (l != null) { - ois.addListener(l::updateProgress); - } - return readAndKeepFeatures(config, entry, in, ois, false); - } - } catch (CityGMLReadException | IOException e) { - throw new CityGmlParseException("Failed to read CityGML file", e); - } catch (Exception e) { - throw new CityGmlParseException(e); - } - } - - private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, CityGmlZipEntry entry, - CityGMLInputFactory inputFactory, ObservedInputStream ois, boolean verbose) throws CityGMLReadException { - return readAndKeepModel(new Citygml3FeatureMapper(config, entry), inputFactory, ois, verbose); - } - - private static List validateStream(InputStream vis, CityGMLContext context) throws CityGmlParseException { - GMLValidationHandler handler = new GMLValidationHandler(); - - try { - BufferedInputStream bis = new BufferedInputStream(vis); - SchemaHandler schemaHandler = new ValidationSchemaHandler(context.getDefaultSchemaHandler()); - readAdditionalSchemaDefinitions(context, bis, schemaHandler); - Source[] schemas = schemaHandler.getSchemas(); - SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - Schema schema = schemaFactory.newSchema(schemas); - Validator validator = schema.newValidator(); - validator.setErrorHandler(handler); - validator.validate(new StreamSource(bis)); - return handler.getMessages(); - } catch (SchemaHandlerException | SAXException | IOException e) { - throw new CityGmlParseException("Failed to validate CityGML file", e); - } - } - - private static void readAdditionalSchemaDefinitions(CityGMLContext context, BufferedInputStream bis, SchemaHandler schemaHandler) - throws CityGmlParseException { - bis.mark(Integer.MAX_VALUE); - try (XMLReader reader = XMLReaderFactory.newInstance(context.getXMLObjects()) - .withSchemaHandler(schemaHandler) - .createReader(bis)) { - reader.nextTag(); - bis.reset(); - } catch (Exception e) { - throw new CityGmlParseException("Failed to read Schema from stream.", e); - } - } - - private static void readEpsgCodeFromInputStream(BufferedInputStream bis, ParserConfiguration config) throws CityGmlParseException { - try { - // Mark start position of GML-"file" - bis.mark(Integer.MAX_VALUE); - // Buffer the first 10000 chars of the Stream, EPSG/envelope info should be found within that range - int peekingWidth = Math.min(10000, bis.available()); - byte[] buf = new byte[peekingWidth]; - bis.read(buf, 0, peekingWidth); - bis.reset(); - parseEpsgCodeFromBuffer(buf, config); - } catch (ParserConfigurationException | SAXException | IOException e) { - throw new CityGmlParseException("Failed to read CityGML file", e); - } - - } - - public static void streamCityGml(CityGmlZipEntry entry, ParserConfiguration config, CityGmlConsumer cityObjectConsumer, - String outputFile) throws CityGmlParseException, IOException { - try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) { - parseEpsgCodeFromStream(entryFile.getInputStream(), config); - startReadingCityGmlZipEntry(entry, config, null, cityObjectConsumer, outputFile); - } catch (ParserConfigurationException | SAXException | IOException e) { - throw new CityGmlParseException("Failed to read CityGML stream", e); - } - } public static void streamCityGml(String file, ParserConfiguration config, CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGmlParseException { @@ -336,7 +299,7 @@ public class CityGmlParser { public static void streamCityGml(Path file, ParserConfiguration config, ProgressListener l, CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGmlParseException { - parseEpsgCodeFromFile(file, config); + parseEpsgCodeFromFile(file, config, true); startReadingCityGmlFile(file, config, l, cityObjectConsumer, outputFile); } @@ -374,31 +337,11 @@ public class CityGmlParser { private static void readAndDiscardFeatures(Path file, ParserConfiguration config, ObservedInputStream ois, CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException { - Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, file); + Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, file, false); readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile); } - private static void startReadingCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l, - CityGmlConsumer cityObjectConsumer, String outputFile) { - try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry); - ObservedInputStream ois = new ObservedInputStream(entryFile.getInputStream(), entry.getFileSize())) { - if (l != null) { - ois.addListener(l::updateProgress); - } - streamAndDiscardFeatures(entry, config, ois, cityObjectConsumer, outputFile); - } catch (IOException | CityGMLReadException e) { - logger.error(Localization.getText("CityGmlParser.errorReadingGmlFile"), e.getMessage()); - logger.catching(Level.ERROR, e); - } - } - - private static void streamAndDiscardFeatures(CityGmlZipEntry entry, ParserConfiguration config, ObservedInputStream ois, - CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException { - Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, entry); - readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile); - } - private static void readAndDiscardModel(Citygml3FeatureMapper mapper, ObservedInputStream ois, CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException { getContext(); @@ -485,8 +428,9 @@ public class CityGmlParser { } private static CityDoctorModel readAndKeepFeatures(ParserConfiguration config, Path file, - CityGMLInputFactory inputFactory, ObservedInputStream ois, boolean verbose) throws CityGMLReadException { - return readAndKeepModel(new Citygml3FeatureMapper(config, file), inputFactory, ois, verbose); + CityGMLInputFactory inputFactory, ObservedInputStream ois, + boolean verbose, boolean unconnected) throws CityGMLReadException { + return readAndKeepModel(new Citygml3FeatureMapper(config, file, unconnected), inputFactory, ois, verbose); } private static CityDoctorModel readAndKeepModel(Citygml3FeatureMapper mapper, CityGMLInputFactory inputFactory, @@ -497,54 +441,75 @@ public class CityGmlParser { // object members are replaced by href in model // need to remove the refs and re-add unparsed objects List acos = new ArrayList<>(); - while (reader.hasNext()) { - AbstractFeature chunk = reader.next(); - version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI()); - if (chunk instanceof CityModel cModel) { - cModel.setCityObjectMembers(null); - mapper.setCityModel(cModel); - mapper.setCityGMLVersion(version); - } else if (chunk instanceof AbstractCityObject aco) { - acos.add(aco); - aco.accept(mapper); + CityModel cgmlModel = null; + CityDoctorModel cdModel = mapper.getModel(); + AutoCloseable parsingContext = cdModel.getCache().startParsingMode(); + try (parsingContext){ + List queuedObjects = new ArrayList<>(); + while (reader.hasNext()) { + AbstractFeature chunk = reader.next(); + version = CityGMLModules.getCityGMLVersion(reader.getName().getNamespaceURI()); + if (chunk instanceof CityModel cModel) { + cModel.setCityObjectMembers(null); + mapper.setCityModel(cModel); + mapper.setCityGMLVersion(version); + cgmlModel = cModel; + + if (!queuedObjects.isEmpty()) { + for (AbstractCityObject aco : queuedObjects) { + if (!cdModel.containsGmlId(aco.getId())) { + cgmlModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco)); + } + } + } + } else if (chunk instanceof AbstractCityObject aco) { + acos.add(aco); // getid + String id = aco.getId(); + aco.accept(mapper); + if (cgmlModel == null) { + // Add object to queue till the CityModel has been parsed + queuedObjects.add(aco); + }else if (!cdModel.containsGmlId(id)){ + cgmlModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco)); + } + } } - } - if (mapper.getModel().getCityModel() == null) { - // file does not contain a city model? - // create it for now - mapper.setCityModel(new CityModel()); - } - CityModel cModel = mapper.getModel().getCityModel(); - - // remove those that should have been parsed - List parsedCityObjects = mapper.getModel().createFeatureStream() - .map(CityObject::getGmlObject).toList(); - acos.removeAll(parsedCityObjects); - // re-add all not parsed objects - for (AbstractCityObject aco : acos) { - cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco)); - } - if (logger.isInfoEnabled() && verbose) { - logger.info(Localization.getText("CityGmlParser.parsedObjects"), - mapper.getModel().getNumberOfFeatures()); + if (mapper.getModel().getCityModel() == null) { + // file does not contain a city model? + // create it for now + logger.warn(Localization.getText("CityGmlParser.missingCityModel")); + mapper.setCityModel(new CityModel()); + for (AbstractCityObject aco : queuedObjects) { + if (!cdModel.containsGmlId(aco.getId())) { + mapper.getModel().getCityModel().getCityObjectMembers().add(new AbstractCityObjectProperty(aco)); + } + } + } + + ImplicitGeometryHolder.resolveDeferredObjects(mapper.getModel().getCache()); + if (logger.isInfoEnabled() && verbose) { + logger.info(Localization.getText("CityGmlParser.parsedObjects"), + mapper.getModel().getNumberOfFeatures()); + } + mapper.setCityGMLVersion(version); + return mapper.getModel(); + } catch (Exception e) { + throw new CityGMLReadException(e); } - // After parsing is complete, try to resolve deferred RelativeGeometries - ImplicitGeometryHolder.resolveDeferredObjects(); - mapper.setCityGMLVersion(version); - return mapper.getModel(); + } } - private static void parseEpsgCodeFromFile(Path file, ParserConfiguration config) throws CityGmlParseException { + private static void parseEpsgCodeFromFile(Path file, ParserConfiguration config, boolean verbose) throws CityGmlParseException { try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file.toFile()))) { - parseEpsgCodeFromStream(bis, config); + parseEpsgCodeFromStream(bis, config, verbose); } catch (ParserConfigurationException | SAXException | IOException e) { throw new CityGmlParseException("Failed to read CityGML file", e); } } - private static void parseEpsgCodeFromStream(InputStream is, ParserConfiguration config) + private static void parseEpsgCodeFromStream(InputStream is, ParserConfiguration config, boolean verbose) throws ParserConfigurationException, SAXException { SAXParser parser = FACTORY.newSAXParser(); CityGmlHandler handler = new CityGmlHandler(); @@ -552,46 +517,19 @@ public class CityGmlParser { parser.parse(new InputSource(is), handler); } catch (EnvelopeFoundException e) { try { - parseCoordinateSystem(config, handler); + parseCoordinateSystem(config, handler, verbose); } catch (Exception e2) { logEpsgParseError(e2); } } catch (Exception e) { logEpsgParseError(e); } - if (handler.getEpsg() == null && logger.isInfoEnabled()) { + if (handler.getEpsg() == null && logger.isInfoEnabled() && verbose) { logger.info(Localization.getText("CityGmlParser.missingEPSGCode")); } } - private static void parseEpsgCodeFromBuffer(byte[] buffer, ParserConfiguration config) - throws ParserConfigurationException, SAXException { - InputStream is = new ByteArrayInputStream(buffer); - SAXParser parser = FACTORY.newSAXParser(); - CityGmlHandler handler = new CityGmlHandler(); - try { - parser.parse(new InputSource(is), handler); - } catch (EnvelopeFoundException e) { - try { - parseCoordinateSystem(config, handler); - - } catch (Exception e2) { - logEpsgParseError(e2); - } - } catch (SAXParseException spe) { - // suppress XML document structure warning - if (!spe.getMessage().matches("XML document structures must start and end within the same entity.")) { - logEpsgParseError(spe); - } - } catch (Exception e) { - logEpsgParseError(e); - } - if (handler.getEpsg() == null && logger.isInfoEnabled()) { - logger.info(Localization.getText("CityGmlParser.missingEPSGCode")); - } - } - private static void logEpsgParseError(Exception e) { logger.debug("Exception while parsing for EPSG code", e); if (logger.isWarnEnabled()) { @@ -599,7 +537,7 @@ public class CityGmlParser { } } - private static void parseCoordinateSystem(ParserConfiguration config, CityGmlHandler handler) { + private static void parseCoordinateSystem(ParserConfiguration config, CityGmlHandler handler, boolean verbose) { if (handler.getEpsg() == null) { return; } @@ -607,14 +545,14 @@ public class CityGmlParser { if (crs == null) { // could not find a coordinate system for srsName // assuming metric system - if (logger.isInfoEnabled()) { + if (logger.isInfoEnabled() && verbose) { logger.info(Localization.getText("CityGmlParser.missingEPSGCode")); } return; } if (crs.getProjection().getUnits() == Units.METRES) { // coordinate system is in meters, do not convert - if (logger.isInfoEnabled()) { + if (logger.isInfoEnabled() && verbose) { logger.info(Localization.getText("CityGmlParser.noConversionNeeded")); } return; @@ -639,11 +577,15 @@ public class CityGmlParser { CoordinateReferenceSystem utm; if (centerLat < 0) { // south - logger.info("Converting coordiante system to UTM zone {}S", zone); + if (logger.isInfoEnabled() && verbose) { + logger.info(Localization.getText("CityGmlParser.convertCrsToUtmZoneS"), zone); + } utm = CRS_FACTORY.createFromParameters("UTM", "+proj=utm +ellps=WGS84 +units=m +zone=" + zone + " +south"); } else { // north - logger.info("Converting coordiante system to UTM zone {}N", zone); + if (logger.isInfoEnabled() && verbose) { + logger.info(Localization.getText("CityGmlParser.convertCrsToUtmZoneN"), zone); + } utm = CRS_FACTORY.createFromParameters("UTM", "+proj=utm +ellps=WGS84 +units=m +zone=" + zone); } config.setCoordinateSystem(crs, utm); @@ -759,22 +701,14 @@ public class CityGmlParser { } private static void drainCityModel(CityDoctorModel model, CityGmlConsumer cityObjectConsumer) { - drainCityObjectList(model.getBuildings(), cityObjectConsumer); - drainCityObjectList(model.getBridges(), cityObjectConsumer); - drainCityObjectList(model.getVegetation(), cityObjectConsumer); - drainCityObjectList(model.getLand(), cityObjectConsumer); - drainCityObjectList(model.getTransportation(), cityObjectConsumer); - drainCityObjectList(model.getWater(), cityObjectConsumer); - drainCityObjectList(model.getTunnels(), cityObjectConsumer); - drainCityObjectList(model.getCityFurniture(), cityObjectConsumer); - drainCityObjectList(model.getGenericCityObjects(), cityObjectConsumer); - } - - private static void drainCityObjectList(List objects, CityGmlConsumer cityObjectConsumer) { - for (CityObject co : objects) { + List id = new ArrayList<>(); + model.createFeatureStream().forEach(co -> { cityObjectConsumer.accept(co); - } - objects.clear(); + id.add(co.getGmlId()); + }); + id.forEach(model::removeFeature); + } + } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/ArchivePacker.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/ArchivePacker.java deleted file mode 100644 index feadacb3175f2e7e61bbf1d04f41e8c0eefbb030..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/ArchivePacker.java +++ /dev/null @@ -1,98 +0,0 @@ -package de.hft.stuttgart.citydoctor2.utils; - -import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -public class ArchivePacker { - - private static final Logger logger = LogManager.getLogger(ArchivePacker.class); - - private ArchivePacker(){} - - public static void packArchive(String targetPath, CityGmlZipArchive archive){ - Path outputPath = Path.of(targetPath); - outputPath = outputPath.getParent().resolve( - FilenameUtils.removeExtension(outputPath.getFileName().toString()) + ".zip"); - Path tmpDir = null; - try{ - tmpDir = Files.createTempDirectory("zipTmp"); - tmpDir.toFile().deleteOnExit(); - for (CityGmlZipEntry entry : archive.getEntries()) { - if (entry.getErrorType() != null || !entry.isLoaded()) { - continue; - } - CityDoctorModel model = entry.getModel(); - Path filePath = tmpDir.resolve(entry.getEntrySubPath()); - Files.createDirectories(filePath.getParent()); - model.saveAs(filePath.toString(), model.isValidated()); - } - zipFolder(tmpDir.toFile(), outputPath.toFile()); - - }catch (Exception e){ - logger.error(e); - } finally { - if (tmpDir != null) { - try { - FileUtils.deleteDirectory(tmpDir.toFile()); - } catch (IOException e) { - logger.error(e); - } - } - } - } - - - public static void zipFolder(File folder, File zipFile) throws IOException { - zipFolder(folder, new FileOutputStream(zipFile)); - } - - public static void zipFolder(File folder, OutputStream outputStream) throws IOException { - try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) { - processFolder(folder, zipOutputStream, folder.getPath().length() + 1); - } - } - - private static void processFolder(File folder, ZipOutputStream zipOutputStream, int prefixLength) - throws IOException { - for (File file : folder.listFiles()) { - if (file.isFile()) { - ZipEntry zipEntry = new ZipEntry(file.getPath().substring(prefixLength)); - zipOutputStream.putNextEntry(zipEntry); - try (FileInputStream inputStream = new FileInputStream(file)) { - IOUtils.copy(inputStream, zipOutputStream); - } - zipOutputStream.closeEntry(); - } else if (file.isDirectory()) { - processFolder(file, zipOutputStream, prefixLength); - } - } - } - - public static void packAndDeleteDirectory(String directoryPath) throws IOException { - Path sourcePath = Path.of(directoryPath); - if (!Files.exists(sourcePath)) { - throw new IllegalStateException("Directory " + directoryPath + " does not exist"); - } - - if (!Files.isDirectory(sourcePath)) { - throw new IllegalStateException("Path " + directoryPath + " is not a directory"); - } - Path outputPath = sourcePath.getParent().resolve(sourcePath.getFileName() + ".zip"); - zipFolder(sourcePath.toFile(), outputPath.toFile()); - - FileUtils.deleteDirectory(sourcePath.toFile()); - } - -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java index 80bace6d75afe5daf1b155604cddd912fbf46689..1285b0c741c3abed146f215f8edb082f2e0aff8f 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java @@ -97,7 +97,6 @@ public class BoundingBoxCalculator { * @return the bounding box of the model */ public static BoundingBox calculateBoundingBox(CityDoctorModel model) { - // TODO: Rework to Visitor MinMaxExtentVisitor mima = new MinMaxExtentVisitor(); model.accept(mima); diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/TimeFormatter.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/TimeFormatter.java new file mode 100644 index 0000000000000000000000000000000000000000..509bdfaa3a81bba4831de362d7937dfd159c8f54 --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/TimeFormatter.java @@ -0,0 +1,62 @@ +package de.hft.stuttgart.citydoctor2.utils; + +import java.text.ChoiceFormat; + +public final class TimeFormatter { + + private TimeFormatter(){} + + private static final String LESS_THAN_A_SECOND = + Localization.getText("TimeFormatter.lessThanASecond"); + + private static final ChoiceFormat SECONDS = + new ChoiceFormat( + new double[]{1, 2}, + new String[]{Localization.getText("TimeFormatter.oneSecond"), + Localization.getText("TimeFormatter.seconds")} + ); + + private static final ChoiceFormat MINUTES = + new ChoiceFormat( + new double[]{1, 2}, + new String[]{Localization.getText("TimeFormatter.oneMinute"), + Localization.getText("TimeFormatter.minutes")} + ); + + private static final ChoiceFormat HOURS = + new ChoiceFormat( + new double[] {1, 2}, + new String[]{Localization.getText("TimeFormatter.oneHour"), + Localization.getText("TimeFormatter.hours")} + ); + + /** + * Formats a time measurement in milliseconds as a localized String representation. + * + *

+ * The String representation will return the time as a rounded down integer of the biggest fitting TimeUnit + * (seconds, minutes or hours), returning "< 1 second" for times under a second. + *

+ * @param millis + * @return A localized String representation of the timespan + */ + public static String format(long millis) { + if (millis < 1000) { + return LESS_THAN_A_SECOND; + }else if (millis < 60_000) { + long seconds = millis / 1000; + String pattern = SECONDS.format(seconds); + return pattern.replace("{0}", Long.toString(seconds)); + }else if (millis < 3_600_000){ + long minutes = millis / 60_000; + String pattern = MINUTES.format(minutes); + return pattern.replace("{0}", Long.toString(minutes)); + } else { + long hours = millis / 3_600_000; + String pattern = HOURS.format(hours); + return pattern.replace("{0}", Long.toString(hours)); + } + + + } +} \ No newline at end of file diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/writer/CityGMLWriterUtils.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/writer/CityGMLWriterUtils.java index 4069621e5d79b0386bb5f9d4885ef4243b1d482a..e3b9cbfb9cfba0e2eed6f3dbaa57e6a93cf15f71 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/writer/CityGMLWriterUtils.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/writer/CityGMLWriterUtils.java @@ -22,12 +22,12 @@ import java.io.File; import java.time.ZonedDateTime; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -92,7 +92,7 @@ public class CityGMLWriterUtils { storeCityObjects(model.getTransportation(), gmlFactory, model, cModel, val); storeCityObjects(model.getWater(), gmlFactory, model, cModel, val); storeCityObjects(model.getCityFurniture(), gmlFactory, model, cModel, val); - storeCityObjects(model.getGenericCityObjects(), gmlFactory, model, cModel, val); + storeCityObjects(model.getOtherCityObjects(), gmlFactory, model, cModel, val); storeCityObjects(model.getTunnels(), gmlFactory, model, cModel, val); writer.write(cModel); @@ -135,12 +135,13 @@ public class CityGMLWriterUtils { de.hft.stuttgart.quality.model.enums.ErrorId adeId = QualityADEUtils.mapErrorIdToAdeId(e.getKey()); if (adeId == null) { // error that is not part of the ade standard - logger.warn("Found error {} that cannot be converted to ADE error. It will not be written", e.getKey()); + logger.warn(Localization.getText("CityGmlWriterUtils.unknownADEError"), e.getKey()); continue; } stats.setName(adeId); statistics.getErrors().add(new ErrorProperty(stats)); } + // TODO: Quality ADE update to CityGML 3.0 statistics.setNumErrorBuildings(new FeatureStatisticsProperty(countValidatedCityObjects(model.getBuildings()))); statistics.setNumErrorBridgeObjects(new FeatureStatisticsProperty(countValidatedCityObjects(model.getBridges()))); statistics.setNumErrorLandObjects(new FeatureStatisticsProperty(countValidatedCityObjects(model.getLand()))); @@ -152,29 +153,30 @@ public class CityGMLWriterUtils { return val; } - private static FeatureStatistics countValidatedCityObjects(List cos) { - int numChecked = 0; - int numError = 0; - for (CityObject co : cos) { + private static FeatureStatistics countValidatedCityObjects(Stream cos) { + AtomicInteger numChecked = new AtomicInteger(); + AtomicInteger numError = new AtomicInteger(); + cos.forEach(co -> { if (co.isValidated()) { - numChecked++; + numChecked.getAndIncrement(); if (co.containsAnyError()) { - numError++; + numError.getAndIncrement(); } } - } - return new FeatureStatistics(numChecked, numError); + }); + return new FeatureStatistics(numChecked.get(), numError.get()); } - private static void storeCityObjects(List cos, GeometryFactory gmlFactory, CityDoctorModel model, CityModel cModel, Validation val) { - for (CityObject co : cos) { + private static void storeCityObjects(Stream cos, GeometryFactory gmlFactory, CityDoctorModel model, CityModel cModel, Validation val) { + cos.forEach(co -> { if (model.isValidated() && val != null) { QualityADEUtils.writeQualityAde(co, val); } co.reCreateGeometries(gmlFactory, model.getParserConfig()); cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(co.getGmlObject())); - } + }); + } } diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java deleted file mode 100644 index be6e4cda33b7f24ea127a9f14ed48ae55fa21b27..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipArchive.java +++ /dev/null @@ -1,151 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; -import de.hft.stuttgart.citydoctor2.utils.ArchivePacker; -import de.hft.stuttgart.citydoctor2.utils.Localization; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.Serial; -import java.io.Serializable; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; - -/** - * This class serves as a representation of a ZIP-archive containing CityGml files. The contained files are represented - * by {@link CityGmlZipEntry} objects. - */ -public class CityGmlZipArchive implements Serializable { - - private static final Logger logger = LogManager.getLogger(CityGmlZipArchive.class); - - @Serial - private static final long serialVersionUID = 2168389511043362615L; - - private List entries; - private final Path archivePath; - private final String archiveNameRE; - - /** - * Registers a ZIP-file as an archive. All contained XML and GML files will be registered as {@link CityGmlZipEntry} objects. - * - * @param zipFile path of the ZIP-file - * @return A {@link CityGmlZipArchive} object representing the archive, or null if read-access for the ZIP-file was denied - * @throws MalformedZipFileException if the ZIP-file has encoding errors - */ - public static CityGmlZipArchive register(String zipFile) throws MalformedZipFileException { - ArrayList archiveEntries = new ArrayList<>(); - CityGmlZipArchive cgmlArchive = new CityGmlZipArchive(Path.of(zipFile)); - try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { - ZipEntry ze; - while ((ze = zis.getNextEntry()) != null) { - if (ze.isDirectory()) { - continue; - } - if (ze.getName().endsWith(".gml") || ze.getName().endsWith(".xml")) { - // Ignore report files generated by CityDoctor - if (ze.getName().endsWith("_report.xml")) { - continue; - } - archiveEntries.add(CityGmlZipEntry.register(ze, cgmlArchive)); - } - } - cgmlArchive.setEntries(archiveEntries); - return cgmlArchive; - } catch (IOException e) { - logger.error(Localization.getText("CityGmlZipArchive.ioError")); - logger.debug(e.getMessage(), e); - return null; - } catch (IllegalArgumentException e) { - logger.error(Localization.getText("CityGmlZipArchive.malformedZipFile")); - throw new MalformedZipFileException(Localization.getText("CityGmlZipArchive.malformedZipFile")); - } catch (Exception e) { - logger.error(Localization.getText("CityGmlZipArchive.generalException")); - logger.debug(e.getMessage(), e); - throw (e); - } - } - - /** - * Attempts to load all contained {@link CityGmlZipEntry} objects into memory. - * - * @param config Parser configuration for the entries - */ - public void mountArchive(ParserConfiguration config) { - try (ZipFile zip = new ZipFile(archivePath.toFile())) { - for (CityGmlZipEntry entry : entries) { - entry.loadEntry(config); - } - } catch (IOException e) { - logger.error(e); - } - } - - private CityGmlZipArchive(Path archivePath) { - this.archivePath = archivePath; - this.archiveNameRE = archivePath.getFileName().toString().replace(".zip", "") + File.separator; - } - - private void setEntries(List entries) { - this.entries = entries; - } - - /** - * Saves this archive as a ZIP-file. - * @param path target path for the export - */ - public void exportToZipFile(String path) { - ArchivePacker.packArchive(path, this); - } - - /** - * Gets an entry in this archive by its subpath. - * - * @param subpath subpath to the entry from this archive's root directory - * @return the corresponding entry, or null if entry could not be found - */ - public CityGmlZipEntry getEntry(String subpath) { - subpath = stripArchivePath(subpath); - for (CityGmlZipEntry entry : entries) { - String entryName = stripArchivePath(entry.getEntrySubPath()); - if (entryName.equals(subpath)) { - return entry; - } - } - return null; - } - - /** - * Strips the root directory name of this archive from an entry subpath. - * @param path the relative path to the entry - * @return String of the path without the root directory - */ - private String stripArchivePath(String path) { - Path systemPath = Path.of(path); - return systemPath.toString().replace(archiveNameRE, ""); - } - - /** - * Gets the path to the ZIP-file associated with this archive. - * @return path of the ZIP-file - */ - public Path getArchivePath() { - return archivePath; - } - - /** - * Gets the entry list of this archive. - * @return the entry list - */ - public List getEntries() { - return entries; - } - -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java deleted file mode 100644 index d9a86770b90e4f6e5703bf1a31adfda17080d9bd..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntry.java +++ /dev/null @@ -1,211 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; -import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; -import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; -import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; -import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; -import de.hft.stuttgart.citydoctor2.parser.ProgressListener; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.io.Serial; -import java.io.Serializable; -import java.nio.file.Path; -import java.util.zip.ZipEntry; - -/** - * This class serves as a representation of a CityGml file in a ZIP archive. - *

- * The {@link CityDoctorModel} of the associated file can only be accessed after loading the corresponding entry. - */ -public class CityGmlZipEntry implements Serializable { - - private static final Logger logger = LogManager.getLogger(CityGmlZipEntry.class); - @Serial - private static final long serialVersionUID = -5732913269959043262L; - - private final Path filePath; - private final String fileName; - private final String displayName; - private transient CityDoctorModel model; - private CityGmlZipArchive parentArchive; - private boolean inMemory; - private long fileSize = -1L; - private static final long MB = 1024 * 1024L; - private ZipEntryErrorType errorType = null; - - - /** - * Attempts to parse the CityGML model associated with this entry and loads it into memory. - *

- * In the event of a parsing error, the entry will be flagged by assigning the appropriate - * {@link ZipEntryErrorType} to the errorType field. - * - * @param config Parser configuration for this model - */ - public void loadEntry(ParserConfiguration config) { - loadEntry(config, null); - } - - /** - * Attempts to parse the CityGML model associated with this entry and loads it into memory. - *

- * In the event of a parsing error, the entry will be flagged by assigning the appropriate - * {@link ZipEntryErrorType} to the errorType field. - * - * @param config Parser configuration for this model - * @param l ProgressListener for tracking parsing progress - */ - public void loadEntry(ParserConfiguration config, ProgressListener l) { - if (inMemory) { - return; - } - if (errorType != null) { - logger.warn("Tried loading erroneous CityGmlZipEntry"); - return; - } - try { - this.model = CityGmlParser.parseCityGmlZipEntry(this, config, l); - this.inMemory = true; - } catch (CityGmlParseException | InvalidGmlFileException e) { - logger.error(e); - this.errorType = ZipEntryErrorType.INVALID_CITY_GML_FILE; - } catch (IOException e) { - logger.error(e); - this.errorType = ZipEntryErrorType.IO_ERROR; - } - } - - /** - * Registers a {@link ZipEntry ZipEntry} in a ZIP-archive as a {@link CityGmlZipEntry}. - *

- * If the filesize of the associated file exceeds the total available system memory, or read access is denied, - * the entry will be flagged by assigning the appropriate {@link ZipEntryErrorType} to the errorType field. - * - * @param entry The ZipEntry object - * @param parentArchive The parent archive for this entry - * @return A corresponding CityGmlZipEntry object - */ - public static CityGmlZipEntry register(ZipEntry entry, CityGmlZipArchive parentArchive) { - CityGmlZipEntry cgzEntry = new CityGmlZipEntry(entry, parentArchive, false); - try { - if (!cgzEntry.entrySizeWithinMemoryLimits()) { - cgzEntry.errorType = ZipEntryErrorType.EXCESSIVE_FILESIZE; - } - } catch (IOException e) { - logger.error(e); - cgzEntry.errorType = ZipEntryErrorType.IO_ERROR; - } - return cgzEntry; - } - - /** - * Checks if the filesize of this entry would exceed the system's available memory. - * - * @return true if within limits, false otherwise - * @throws IOException if read access to the ZIP-archive is denied - */ - private boolean entrySizeWithinMemoryLimits() throws IOException { - long memoryLimit = (long) Math.ceil(((double) Runtime.getRuntime().maxMemory() / MB) * 0.9); - if (fileSize == -1L) { - try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(this)) { - long filesize = entryFile.getFileSize(); - if (filesize != -1) { - this.fileSize = filesize; - } else { - return false; - } - } catch (Exception e) { - throw new IOException(e); - } - } - return memoryLimit > (fileSize / MB); - } - - private CityGmlZipEntry(ZipEntry entry, CityGmlZipArchive parentArchive, boolean inMemory) { - this.fileName = entry.getName(); - this.filePath = Path.of(entry.getName()); - this.displayName = filePath.getFileName().toString(); - if (entry.getSize() != -1) { - this.fileSize = entry.getSize(); - } - this.model = null; - this.inMemory = inMemory; - this.parentArchive = parentArchive; - } - - /** - * Gets the parent archive of this entry. - * @return the archive - */ - public CityGmlZipArchive getArchive() { - return parentArchive; - } - - /** - * Gets the sub-path in the archive of the file associated with this entry. - * - * @return the relative sub-path from the archive root directory - */ - public String getEntrySubPath() { - return fileName; - } - - /** - * Gets the name of the file associated with this entry. - * @return the filename - */ - public String getDisplayName() { - return displayName; - } - - /** - * Gets the {@link ZipEntryErrorType} of this entry. - * @return the error type, or null if this entry is not erroneous - */ - public ZipEntryErrorType getErrorType() { - return errorType; - } - - /** - * Gets the {@link CityDoctorModel} of this entry. - * @return The model, or null if the entry has not been loaded or is erroneous - */ - public CityDoctorModel getModel() { - return model; - } - - public void setFileSize(long size) { - fileSize = size; - } - - /** - * Resolves the reference path of a {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject LibraryObject} - * in the {@link CityDoctorModel} of this entry. - * @param libraryObjectPath The reference path to the LibraryObject's CityGml file - * @return Relative sub-path within the archive to the CityGml file - */ - public Path resolveLibraryObjectPath(String libraryObjectPath) { - return filePath.getParent().resolve(libraryObjectPath); - } - - /** - * Checks if the {@link CityDoctorModel} of this entry has been loaded into memory. - * - * @return true if it is loaded, false otherwise - */ - public boolean isLoaded() { - return inMemory; - } - - /** - * Returns the estimated uncompressed filesize of this entry. - * - * @return filesize in bytes, -1L if filesize is unknown - */ - public long getFileSize() { - return fileSize; - } -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntryFile.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntryFile.java deleted file mode 100644 index 3bf82fe00a2490d9eef2eb715ef6edc5a4a14786..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/CityGmlZipEntryFile.java +++ /dev/null @@ -1,79 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * This class serves as a resource for read-access to the file that is being represented by - * a CityGmlZipEntry object. - *

- * Does not decompress the file or the parent ZIP-archive. - */ -public class CityGmlZipEntryFile implements AutoCloseable { - - private final ZipFile zip; - private final ZipEntry zipEntry; - private final CityGmlZipEntry cgmlZipEntry; - private boolean closed = false; - - /** - * Creates a {@link CityGmlZipEntryFile} for a {@link CityGmlZipEntry} object's referenced file. - * - * @param entry the requested entry - * @throws IOException if read access to the ZIP-archive is denied. - */ - public CityGmlZipEntryFile(CityGmlZipEntry entry) throws IOException { - CityGmlZipArchive archive = entry.getArchive(); - zip = new ZipFile(archive.getArchivePath().toFile()); - zipEntry = zip.getEntry(entry.getEntrySubPath()); - this.cgmlZipEntry = entry; - } - - /** - * Gets a new InputStream of this file. - *

- * Returned streams are independent of each other, but will all be closed when the {@link CityGmlZipEntryFile} object - * is closed. - * @return an InputStream of this file. - * @throws IOException when this method is called after the file has been closed. - */ - public InputStream getInputStream() throws IOException { - if (closed){ - throw new IOException("CityGmlZipEntryFile closed"); - } - return zip.getInputStream(zipEntry); - } - - /** - * Gets an estimation of this file's filesize. - * @return filesize in bytes, -1L if unknown - * @throws IOException when this method is called after the file has been closed. - */ - public long getFileSize() throws IOException { - if (closed){ - throw new IOException("CityGmlZipEntryFile closed"); - } - if (cgmlZipEntry.getFileSize() == -1L) { - if (zipEntry.getSize() == -1) { - long bytes = 0; - InputStream is = new BufferedInputStream(this.getInputStream()); - for (int i = is.read(); i != -1; i = is.read()) { - bytes++; - } - cgmlZipEntry.setFileSize(bytes); - } else { - cgmlZipEntry.setFileSize(zipEntry.getSize()); - } - } - return cgmlZipEntry.getFileSize(); - } - - @Override - public void close() throws IOException { - zip.close(); - closed = true; - } -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/MalformedZipFileException.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/MalformedZipFileException.java deleted file mode 100644 index 759fbe6bffca2ee965fbbb0b84a35b6202398084..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/MalformedZipFileException.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -import java.util.zip.ZipException; - -/** - * Signals that a ZIP-file is corrupted and couldn't be parsed. - */ -public class MalformedZipFileException extends ZipException { - - public MalformedZipFileException() { - super(); - } - - public MalformedZipFileException(String message) { - super(message); - } -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/ZipEntryErrorType.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/ZipEntryErrorType.java deleted file mode 100644 index 7dec72b42b00da211c994f85d05005916e9430bf..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/ZipEntryErrorType.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -/** - * Error types for {@link CityGmlZipEntry} objects. - */ -public enum ZipEntryErrorType { - INVALID_CITY_GML_FILE, EXCESSIVE_FILESIZE, IO_ERROR -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/ZipParser.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/ZipParser.java deleted file mode 100644 index e65d96b82ad2b8f3d29109348ccf6bb22107de2e..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/zip/ZipParser.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class ZipParser { - - private static final Logger logger = LogManager.getLogger(ZipParser.class); - - - -} diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties index 78349133d6520a64c71648949f2205e4c513add6..59ecf4ef6cf2cbcb46cf92569781ccb940c2ff54 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties +++ b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties @@ -1,173 +1,201 @@ -CityDoctorValidation.Version=${versionString} -DistanceError.distanceFromPlane=distance from plane -AboutDialog.developedBy=Developed by +AboutDialog.closeBtn=Close AboutDialog.contact=Contact +AboutDialog.developedBy=Developed by AboutDialog.title=CityDoctor 3 - About -AboutDialog.closeBtn=Close -CheckDialog.title=Check Configuration -CheckDialog.schematronFiles=Schematron Files -CheckDialog.schematronChooserTitle=Choose schematron file.. -CheckDialog.validationConfiguration=Validation Configuration -CheckDialog.startingChecks=Starting checks -CheckDialog.checksDone=Checks done -CheckDialog.failedChecks=Failed to execute checks -CheckDialog.schematronFileNotExisting=Schematron file does not exist, ignoring +CheckContainer.error=Unexpected exception while executing check: {} +CheckDialog.availableChecksLabel=Available Checks +CheckDialog.cancelBtn=Cancel +CheckDialog.checkBtn=Check CheckDialog.checkEnabled=Enabled CheckDialog.checkName=Name -CheckDialog.parameterValue=Value +CheckDialog.checksDone=Checks done +CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information. +CheckDialog.checksTab=Checks +CheckDialog.failedChecks=Failed to execute checks +CheckDialog.filterTab=Filter +CheckDialog.geometricChecksLabel=Geometric Checks +CheckDialog.globalParametersLabel=Global Parameters +CheckDialog.noPathError=Output path is missing! +CheckDialog.outputPathBtn=Select +CheckDialog.outputPathLabel=Output directory (Required): CheckDialog.parameterUnit=Unit +CheckDialog.parameterValue=Value +CheckDialog.pdfReportsOption=Create PDF reports +CheckDialog.schematronChooserTitle=Choose schematron file ... +CheckDialog.schematronFileLabel=Schematron File: +CheckDialog.schematronFileNotExisting=Schematron file does not exist, Schematron will be skipped +CheckDialog.schematronFiles=Schematron Files +CheckDialog.selectBtn=Select +CheckDialog.semanticChecksLabel=Semantic Checks +CheckDialog.startingChecks=Starting checks +CheckDialog.streamCheckLabel=Citymodels are not loaded and kept in memory. Check results are saved to the QualityADE in copies of the input files. +CheckDialog.streamCheckOption=Use low memory mode +CheckDialog.title=Check Configuration +CheckDialog.validationConfiguration=Validation Configuration +CheckDialog.xmlReportsOption=Create XML reports +Checker.checkFeature=Checking feature: {} +Checker.checksFinished=Finished executing checks. Total time: {0} +Checker.dbStillUnresponsive=Checker still unable to load some CityObjects from database! +Checker.dbUnresponsive=Checker could not load some CityObjects from database! +Checker.executeCheck=Executing check: {} +Checker.failPdf=Failed to write PDF Report. +Checker.failReports=Failed to write reports. +Checker.failXml=Failed to write XML Error Report. +Checker.finishedSchematron=Finished Schematron validation +Checker.futuresCheckFailures=Encountered check failures due to the following errors: +Checker.noCheckSatisfiesRequirement=Could not find any check that satisfies requirement {}, it will not be checked +Checker.schematronCompleted=Schematron completed +Checker.schematronFileNotFound=Schematron file {} could not be found +Checker.schematronInterrupted=Main Thread was interrupted while waiting for Schematron +Checker.schematronStillRunning=Schematron is still running. Waiting for completion, this may take some time +Checker.schematronValidation=Schematron-validation thread started +Checker.shutdownInterrupted=Main Thread got interrupted during ThreadPool shutdown +Checker.validationInterrupted=Validation aborted: Checker got interrupted +Checker.waitAndRetry=Waiting a second before retrying... +Checks.missingCheck=Could not find check for id: {} +CityDoctorController.exportSuccess=Successfully exported feature CityDoctorController.noDatamodel=Datamodel is null, no checks could be done CityDoctorController.noSourceFile=Source file is null, no checks could be done CityDoctorController.noZipFile=ZIP archive is null, no checks could be done -CityDoctorController.exportSuccess=Successfully exported feature CityDoctorController.saveZipArchiveReports=Successfully exported validation reports! +CityDoctorValidation.Version=${versionString} +CityDoctorValidation.inputFileNotExisting= Input file '{}' does not exist. +CityDoctorValidation.loadingDefaultConfig=No configuration file given, loading default configuration +CityDoctorValidation.noConfig=No configuration file specified with -config [FILE] +CityDoctorValidation.noInputFile=No input file specified. (-in [FILE]) +CityDoctorValidation.noOutputFile=No output file specified. (-out [FILE]) +CityDoctorValidation.notExactlyOneConfigFile=Specify exactly one file as configuration +CityDoctorValidation.notExactlyOneInputFile=Specify exactly one file as input. +CityDoctorValidation.notExactlyOneOutputFile=Specify exactly one file as output. +CityDoctorValidation.notExactlyOnePDFOutput=Specify exactly one file as pdfReport +CityDoctorValidation.notExactlyOneXMLOutput=Specify exactly one file as xmlReport +CityDoctorValidation.wrongInputFileFormat=Input file '{}' does not end with .gml or .xml +CityGmlParser.chunkReadFailed=Failed to read GML file in chunks, falling back to reading the complete file +CityGmlParser.convertCrsToUtmZoneN=Converting coordinate system to UTM zone {}N +CityGmlParser.convertCrsToUtmZoneS=Converting coordinate system to UTM zone {}S +CityGmlParser.creating4jContextFailed=Unable to create citygml4j context +CityGmlParser.creatingAdePluginsFailed=Unable to add ADE plugins to citygml4j +CityGmlParser.errorReadingGmlFile=Error while reading city gml file\n{} +CityGmlParser.errorWritingGmlFile=Error while writing city gml file\n{} +CityGmlParser.failedEPSGParse=Could not read EPSG code, fallback to metric system +CityGmlParser.missingCityModel=File does not contain a CityModel definition! Temporary CityModel will be created. +CityGmlParser.missingEPSGCode=No EPSG code found, assuming metric system +CityGmlParser.noConversionNeeded=Coordinate system is in meters, no conversion done +CityGmlParser.notValidGmlFile=This is not a valid GML-File\n +CityGmlParser.parsedObjects=Parsed model with {} objects +CityGmlWriterUtils.unknownADEError= Found error {} that cannot be converted to ADE error. It will not be written +CityGmlZipArchive.generalException=Encountered an unexpected error while reading the ZIP archive +CityGmlZipArchive.ioError=Accessing the ZIP archive failed +CityGmlZipArchive.malformedZipFile=Parsing of ZIP archive aborted, ZIP file is malformed! +DatabaseHandler.batchCommitFailure=Batch-commit aborted: Critical failure while trying to write CityObject {} to database! +DatabaseHandler.connectionFailure=Connection to embedded database could not be opened! +DatabaseHandler.fetchErrorIdsFailure=Fetching list of GmlIDs of CityObjects with errors failed! +DatabaseHandler.getAllCityObjectsFailure=Fetching of all CityObjects failed! +DatabaseHandler.getBBoxIntersectFailure= Connection to database failed while trying to fetch bbox intersecting objects of CityObject {} +DatabaseHandler.getBufferIntersectFailure=Connection to database failed while trying to fetch buffer intersecting objects of CityObject {} +DatabaseHandler.getFeatureCountFailure=Connection to database failed while trying to get count of CityObjects! +DatabaseHandler.marshallingFailure=Writing CityObject {} to database failed! +DatabaseHandler.serializationFailure=Serialization of CityObject {} failed! +DatabaseHandler.setupFailure=FATAL ERROR: Creation of embedded database failed! +DatabaseHandler.tableFailure=FATAL ERROR: Creation of features table failed! +DatabaseHandler.unmarshallingFailure=Loading of CityObject {} from embedded database failed! +DistanceError.distanceFromPlane=distance from plane +ErrorItemVisitor.childId=Child id +ErrorItemVisitor.component=Component +ErrorItemVisitor.degeneratedRing=Degenerated ring +ErrorItemVisitor.deviation=Deviation +ErrorItemVisitor.distance=Distance +ErrorItemVisitor.intersection=Intersection +ErrorItemVisitor.nameOfAttribute=Name of attribute +ErrorItemVisitor.pointTouchesEdge=Point touches edge +ErrorItemVisitor.triangles=Triangles ExceptionDialog.stacktrace=The exception stacktrace was: -FilterPane.buildings=Buildings +FeatureMapper.polygonUnreferenced=Polygon {} is referenced but not found in feature polygons FilterPane.bridges=Bridges +FilterPane.buildings=Buildings FilterPane.landUse=Land Use FilterPane.transportation=Transportation FilterPane.vegetation=Vegetation FilterPane.water=Water -MainToolBar.wireframe=Show/Hide Wireframe +GeometryMapper.emptyPolygon=Found polygon without exterior ring, ignoring +LibraryObject.fileMissing=Implicit geometry references non-existing library object file {} +LibraryObject.parsingError=Encountered an error while parsing library object {} MainToolBar.culling=Enable/Disable Culling -MainToolBar.writeReports=Write Reports MainToolBar.executeChecks=Execute Checks -MainToolBar.showWorld=Show entire city model -MainToolBar.resetCamera=Reset view MainToolBar.hideRoof=Show/Hide roof BoundarySurfaces +MainToolBar.resetCamera=Reset view +MainToolBar.showWorld=Show entire city model +MainToolBar.wireframe=Show/Hide Wireframe +MainToolBar.writeReports=Write Reports MainToolBar.zip=Open zip-entry selection window -MainWindow.missingConfig=Could not find configuration file. -MainWindow.loadGivenFile=Loading given file, please wait -MainWindow.finishedLoading=Finished loading -MainWindow.checking=Checking, please wait -MainWindow.writeXml=Writing xml report -MainWindow.finishedXml=Finished xml report -MainWindow.writePdf=Writing pdf report -MainWindow.finishedPdf=Finished pdf report -MainWindow.loadFailed=Failed to load given gml file: {} MainWindow.all=All -MainWindow.withErrors=With errors -MainWindow.export=Export feature +MainWindow.attributeTab=Attributes +MainWindow.availableLabel=Available: +MainWindow.bridgeTab=Bridges +MainWindow.buildingsTab=Buildings +MainWindow.checking=Checking, please wait +MainWindow.cityfurnitureTab=CityFurniture +MainWindow.clearBtn=Clear MainWindow.copyId=Copy GML-ID MainWindow.delete=Delete feature -MainWindow.infoTopLevelExport=Only top-level object can be exported! +MainWindow.edgesTab=Edges +MainWindow.errorsTab=Errors +MainWindow.export=Export feature +MainWindow.finishedLoading=Finished loading +MainWindow.finishedPdf=Finished pdf report +MainWindow.finishedXml=Finished xml report +MainWindow.focusCityObject=Focus object +MainWindow.globalErrorsTab=Global Errors MainWindow.infoTopLevelCopyID=GML-ID can only be copied from top-level object! -mainWindow.warnCopyIdFailed=Could not copy GML-ID! -OpenFileDialog.select=Select CityGML file +MainWindow.infoTopLevelExport=Only top-level object can be exported! MainWindow.languageChange=For the change in language to apply, restart CityDoctor2. -MainWindow.buildingsTab=Buildings -MainWindow.vegetationTab=Vegetation -MainWindow.transportationTab=Transportation -MainWindow.tunnelTab=Tunnels -MainWindow.bridgeTab=Bridges -MainWindow.waterTab=Water -MainWindow.terrainTab=Terrain -MainWindow.cityfurnitureTab=CityFurniture +MainWindow.loadFailed=Failed to load given gml file: {} +MainWindow.loadGivenFile=Loading given file, please wait +MainWindow.logTab=Log +MainWindow.memoryLabel=Memory: +MainWindow.missingConfig=Could not find configuration file. MainWindow.otherObjectsTab=Other -MainWindow.viewLabel=View -MainWindow.showLabel=Show: -MainWindow.searchLabel=Search: -MainWindow.searchBtn=Search -MainWindow.clearBtn=Clear -MainWindow.errorsTab=Errors MainWindow.polygonsTab=Polygons -MainWindow.edgesTab=Edges +MainWindow.searchBtn=Search +MainWindow.searchLabel=Search: +MainWindow.showLabel=Show: +MainWindow.terrainTab=Terrain +MainWindow.transportationTab=Transportation +MainWindow.tunnelTab=Tunnels +MainWindow.vegetationTab=Vegetation MainWindow.verticesTab=Vertices -MainWindow.attributeTab=Attributes -MainWindow.logTab=Log -MainWindow.globalErrorsTab=Global Errors -MainWindow.focusCityObject=Focus object +MainWindow.viewLabel=View +MainWindow.warnCopyIdFailed=Could not copy GML-ID! +MainWindow.waterTab=Water +MainWindow.withErrors=With errors +MainWindow.writePdf=Writing pdf report +MainWindow.writeXml=Writing xml report +OpenFileDialog.cancelBtn=Cancel OpenFileDialog.fileLabel=File: -OpenFileDialog.selectBtn=Select OpenFileDialog.loadBtn=Load -OpenFileDialog.settingsPane=Parser Preferences +OpenFileDialog.loadFailed=Failed to load CityGML File +OpenFileDialog.lowMemoryLabel=Low Memory Consumption Mode OpenFileDialog.roundingPlacesLabel=NumberOfRoundingPlaces +OpenFileDialog.select=Select CityGML file +OpenFileDialog.selectBtn=Select +OpenFileDialog.settingsPane=Parser Preferences OpenFileDialog.xmlValidationLabel=Use XML Validation -Checker.failXml=Failed to write XML Error Report. -Checker.failPdf=Failed to write PDF Report. -Checker.checksFinished=Finished executing checks -Checker.schematronValidation=Starting Schematron validation -Checker.finishedSchematron=Finished Schematron validation -Checker.failReports=Failed to write reports. -Checker.checkFeature=Checking feature: {} -Checker.executeCheck=Executing check: {} -ValidationConfiguration.reenable={} has been disabled but {} depends on it, reenabling +TimeFormatter.hours={0} hours +TimeFormatter.lessThanASecond=< 1 second +TimeFormatter.minutes={0} minutes +TimeFormatter.oneHour=1 hour +TimeFormatter.oneMinute=1 minute +TimeFormatter.oneSecond=1 second +TimeFormatter.seconds={0} seconds +Unit.Degree=Degree +Unit.Radian=Radian ValidationConfiguration.missingSchematron={} is not an existing file, disabling schematron check -CheckContainer.error=Unexpected exception while executing check: {} -Checks.missingCheck=Could not find check for id: {} -OpenFileDialog.cancelBtn=Cancel -CheckDialog.checksTab=Checks -CheckDialog.filterTab=Filter -CheckDialog.globalParametersLabel=Global Parameters -CheckDialog.availableChecksLabel=Available Checks -CheckDialog.geometricChecksLabel=Geometric Checks -CheckDialog.semanticChecksLabel=Semantic Checks -CheckDialog.schematronFileLabel=Schematron File: -CheckDialog.selectBtn=Select -CheckDialog.checkBtn=Check -CheckDialog.cancelBtn=Cancel -CheckDialog.streamCheckOption=Use low memory mode -CheckDialog.streamCheckLabel=Citymodels are not loaded and kept in memory. Check results are saved to the QualityADE in copies of the input files. -CheckDialog.outputPathLabel=Output directory (Required): -CheckDialog.outputPathBtn=Select -CheckDialog.pdfReportsOption=Create PDF reports -CheckDialog.xmlReportsOption=Create XML reports -CheckDialog.noPathError=Output path is missing! -ZipEntryManager.title=Zip-entry manager -ZipEntryManager.entryListTitle=Zip-entries -ZipEntryManager.metadata=Metadata -ZipEntryManager.subpathLbl=Subpath: -ZipEntryManager.erroneousLbl=Erroneous: -ZipEntryManager.excessiveFileSize=Filesize exceeds memory -ZipEntryManager.invalidCityGml=Invalid CityGML file -ZipEntryManager.ioError=Unable to access file -ZipEntryManager.filesizeLbl=Filesize: -ZipEntryManager.validatedLbl=Validated: -ZipEntryManager.objectCountLbl=Object count: -ZipEntryManager.loadBtn=Load CityGML model -ZipEntryManager.decompressBtn=Unpack file -ZipEntryManager.decompressAllBtn=Unpack all files -ZipEntryManager.checkAllBtn=Check all files -ZipEntryManager.showReportBtn=Show error statistic -ZipEntryManager.saveBtn=Export validation results -ZipEntryManager.cancelBtn=Cancel -ZipEntryManager.unknownValue=N/A -ZipEntryManager.yes=Yes -ZipEntryManager.no=No -CityGmlZipArchive.ioError=Accessing the ZIP archive failed -CityGmlZipArchive.malformedZipFile=Parsing of ZIP archive aborted, ZIP file is malformed! -CityGmlZipArchive.generalException=Encountered an unexpected error while reading the ZIP archive -WriteReportDialog.writeBtn=Save +ValidationConfiguration.reenable={} has been disabled but {} depends on it, reenabling WriteReportDialog.cancelBtn=Cancel WriteReportDialog.errorStatisticsLabel=Error Statistics WriteReportDialog.saveImageBtn=Save Image... WriteReportDialog.selectPdfBtn=Select WriteReportDialog.selectXmlFile=Select +WriteReportDialog.writeBtn=Save WriteReportDialog.xAxisLabel=Error -WriteReportDialog.yAxisLabel=Count -Unit.Radian=Radian -Unit.Degree=Degree -FeatureMapper.polygonUnreferenced=Polygon {} is referenced but not found in feature polygons -GeometryMapper.emptyPolygon=Found polygon without exterior ring, ignoring -CityGmlParser.parsedObjects=Parsed model with {} objects -CityGmlParser.chunkReadFailed=Failed to read GML file in chunks, falling back to reading the complete file -CityGmlParser.notValidGmlFile=This is not a valid GML-File\n -CityGmlParser.errorReadingGmlFile=Error while reading city gml file\n{} -CityGmlParser.errorWritingGmlFile=Error while writing city gml file\n{} -CityGmlParser.noConversionNeeded=Coordinate system is in meters, no conversion done -CityGmlParser.failedEPSGParse=Could not read EPSG code, fallback to metric system -CityGmlParser.missingEPSGCode=No EPSG code found, assuming metric system -OpenFileDialog.loadFailed=Failed to load CityGML File -MainWindow.memoryLabel=Memory: -CheckDialog.checksReenabledAlert=Some checks have been reenabled so that other wanted checks can be executed\nSee the log for more information. -MainWindow.availableLabel=Available: -OpenFileDialog.lowMemoryLabel=Low Memory Consumption Mode -ErrorItemVisitor.intersection=Intersection -ErrorItemVisitor.component=Component -ErrorItemVisitor.nameOfAttribute=Name of attribute -ErrorItemVisitor.childId=Child id -ErrorItemVisitor.distance=Distance -ErrorItemVisitor.pointTouchesEdge=Point touches edge -ErrorItemVisitor.degeneratedRing=Degenerated ring -ErrorItemVisitor.deviation=Deviation -ErrorItemVisitor.triangles=Triangles \ No newline at end of file +WriteReportDialog.yAxisLabel=Count \ No newline at end of file diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties index 864c13b7b84e9974f1bd6c2b2ab9c6d5e3b45129..e9c1f7b68d35cda5c4a329698fe8801e4d8f31ba 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties +++ b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties @@ -1,171 +1,201 @@ -DistanceError.distanceFromPlane=Abstand von der Ebene -AboutDialog.developedBy=Entwickelt von +AboutDialog.closeBtn=Schlie\u00DFen AboutDialog.contact=Kontakt +AboutDialog.developedBy=Entwickelt von AboutDialog.title=CityDoctor 3 - \u00DCber -AboutDialog.closeBtn=Schlie\u00DFen -CheckDialog.title=Pr\u00fcfungskonfiguration -CheckDialog.schematronFiles=Schematron Dateien -CheckDialog.schematronChooserTitle=W\u00e4hle Schematron Datei.. -CheckDialog.validationConfiguration=Validierungs Konfiguration -CheckDialog.startingChecks=Starte Pr\u00fcfung +CheckContainer.error=Unerwarteter Fehler bei der Ausf\u00fchrung von Pr\u00fcfung: {} +CheckDialog.availableChecksLabel=Verf\u00fcgbare Pr\u00fcfungen +CheckDialog.cancelBtn=Abbrechen +CheckDialog.checkBtn=Pr\u00fcfen +CheckDialog.checkEnabled=Aktiv +CheckDialog.checkName=Name CheckDialog.checksDone=Pr\u00fcfung abgeschlossen +CheckDialog.checksReenabledAlert=Manche Pr\u00fcfungen wurden reaktiviert damit andere gewollte Pr\u00fcfungen durchgef\u00fchrt werden k\u00f6nnen\nMehr Details sind im Log geschrieben +CheckDialog.checksTab=Pr\u00fcfungen CheckDialog.failedChecks=Konnte Pr\u00fcfungen nicht ausf\u00fchren -CheckDialog.schematronFileNotExisting=Schematron Datei existiert nicht, ignoriere -CheckDialog.checkEnabled=Aktiv -CheckDialog.parameterValue=Wert +CheckDialog.filterTab=Filter +CheckDialog.geometricChecksLabel=Geometrische Pr\u00fcfungen +CheckDialog.globalParametersLabel=Globale Parameter +CheckDialog.noPathError=Ausgabepfad wurde nicht gesetzt! +CheckDialog.outputPathBtn=Ausw\u00e4hlen +CheckDialog.outputPathLabel=Ausgabeordner (Pflichtfeld): CheckDialog.parameterUnit=Einheit -CityDoctorController.noDatamodel=Datenmodell ist null, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden -CityDoctorController.noSourceFile=Quelldatei ist null, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden -CityDoctorController.noZipFile=ZIP-Archiv ist null, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden -CityDoctorController.exportSuccess=Feature export erfolgreich abgeschlossen +CheckDialog.parameterValue=Wert +CheckDialog.pdfReportsOption=PDF-Berichte erstellen +CheckDialog.schematronChooserTitle=W\u00e4hle Schematron Datei ... +CheckDialog.schematronFileLabel=Schematron Datei: +CheckDialog.schematronFileNotExisting=Schematron Datei existiert nicht, Schematron-Pr\u00fcfung wird \u00fcbersprungen +CheckDialog.schematronFiles=Schematron Dateien +CheckDialog.selectBtn=Ausw\u00e4hlen +CheckDialog.semanticChecksLabel=Semantische Pr\u00fcfungen +CheckDialog.startingChecks=Starte Pr\u00fcfung +CheckDialog.streamCheckLabel=Stadtmodelle werden nicht in den Arbeitsspeicher geladen. Ergebnisse werden in der QualityADE in Kopien der Eingangsdateien gespeichert. +CheckDialog.streamCheckOption=Niedrigen Arbeitsspeicherverbrauchsmodus aktivieren +CheckDialog.title=Pr\u00fcfungskonfiguration +CheckDialog.validationConfiguration=Validierungskonfiguration +CheckDialog.xmlReportsOption=XML-Berichte erstellen +Checker.checkFeature=Pr\u00fcfe Feature: {} +Checker.checksFinished=Durchf\u00fchrung der Pr\u00fcfungen abgeschlossen. Gesamtzeit: {0} +Checker.dbStillUnresponsive=Pr\u00fcfung konnte weiterhin einige CityObjects nicht aus der Datenbank laden! +Checker.dbUnresponsive=Pr\u00fcfung konnte einige CityObjects nicht aus der Datenbank laden! +Checker.executeCheck=F\u00fchre Pr\u00fcfung aus: {} +Checker.failPdf=Konnte PDF-Fehlerbericht nicht schreiben. +Checker.failReports=Konnte Pr\u00fcfberichte nicht schreiben. +Checker.failXml=Konnte XML-Fehlerbericht nicht schreiben. +Checker.finishedSchematron=Schematron-Pr\u00fcfung abgeschlossen +Checker.futuresCheckFailures=Einige Pr\u00fcfungen sind aufgrund folgender Fehler fehlgeschlagen: +Checker.noCheckSatisfiesRequirement=Keine Pr\u00fcfung erf\u00fcllt die Anforderung {}, Anforderung wird nicht gepr\u00fcft +Checker.schematronCompleted=Schematron-Pr\u00fcfung abgeschlossen +Checker.schematronFileNotFound=Schematron Datei {} konnte nicht gefunden werden +Checker.schematronInterrupted=Main Thread hat Interrupt-Befehl w\u00e4hrend dem Warten auf Schematron Abschluss erhalten! +Checker.schematronStillRunning=Schematron-Pr\u00fcfung ist noch nicht abgeschlossen. Warten auf Abschluss der Pr\u00fcfung, dies kann einiges an Zeit beanspruchen +Checker.schematronValidation=Schematron-Pr\u00fcfung gestartet +Checker.shutdownInterrupted=Main-Thread hat einen Interrupt-Befehl w\u00e4hrend dem ThreadPool shutdown erhalten +Checker.validationInterrupted=Validierung abgebrochen: Pr\u00fcfung hat Interrupt-Befehl erhalten +Checker.waitAndRetry=Wiederhole Pr\u00fcfung nach kurzer Wartezeit ... +Checks.missingCheck=Konnte keine Pr\u00fcfung f\u00fcr id {} finden +CityDoctorController.exportSuccess=Exportieren des Features erfolgreich abgeschlossen +CityDoctorController.noDatamodel=Datenmodell ist NULL, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden +CityDoctorController.noSourceFile=Quelldatei ist NULL, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden +CityDoctorController.noZipFile=ZIP-Archiv ist NULL, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden CityDoctorController.saveZipArchiveReports=Validierungsberichte erfolgreich exportiert! +CityDoctorValidation.Version=${versionString} +CityDoctorValidation.inputFileNotExisting=Eingabedatei '{}' existiert nicht. +CityDoctorValidation.loadingDefaultConfig=Keine Konfigurationsdatei angegeben, Standardkonfiguration wird geladen. +CityDoctorValidation.noConfig=Keine Konfigurationsdatei angegeben. (-config [DATEIPFAD]) +CityDoctorValidation.noInputFile=Keine Eingabedatei angegeben. (-in [DATEIPFAD]) +CityDoctorValidation.noOutputFile=Keinen Ausgabedateipfad angegeben. (-out [DATEIPFAD]) +CityDoctorValidation.notExactlyOneConfigFile=Es muss exakt eine Konfigurationsdatei angegeben werden. +CityDoctorValidation.notExactlyOneInputFile=Es muss exakt eine Eingabedatei angegeben werden. +CityDoctorValidation.notExactlyOneOutputFile=Es muss exakt ein Ausgabedateipfad angegeben werden. +CityDoctorValidation.notExactlyOnePDFOutput=Es muss exakt ein Ausgabedateipfad f\u00fcr den PDF-Bericht angegeben werden. +CityDoctorValidation.notExactlyOneXMLOutput=Es muss exakt ein Ausgabedateipfad f\u00fcr den XML-Bericht angegeben werden. +CityDoctorValidation.wrongInputFileFormat=Eingabedatei '{}' ist keine .gml oder .xml Datei. +CityGmlParser.chunkReadFailed=Konnte Datei nicht in St\u00fccken lesen, versuche komplett zu lesen +CityGmlParser.convertCrsToUtmZoneN=Konvertiere Koordinatensystem zu UTM Zone {}N +CityGmlParser.convertCrsToUtmZoneS=Konvertiere Koordinatensystem zu UTM Zone {}S +CityGmlParser.creating4jContextFailed=Erstellen des Citygml4j Kontext fehlgeschlagen +CityGmlParser.creatingAdePluginsFailed=Erstellen des ADE Plugins f\u00fcr citygml4j fehlgeschlagen +CityGmlParser.errorReadingGmlFile=Fehler beim lesen der CityGML Datei\n{} +CityGmlParser.errorWritingGmlFile=Fehler beim schreiben der CityGML Datei\n{} +CityGmlParser.failedEPSGParse=Lesen des EPSG-Codes fehlgeschlagen, greife auf metrisches System zur\u00fcck +CityGmlParser.missingCityModel=Datei enth\u00e4lt kein CityModel! Tempor\u00e4res CityModel wird erstellt. +CityGmlParser.missingEPSGCode=Kein EPSG-Code wurde gefunden! Gehe von metrischem System aus +CityGmlParser.noConversionNeeded=Koordinatensystem in Metern, keine Konvertierung notwendig +CityGmlParser.notValidGmlFile=Dies ist keine korrekte CityGML Datei +CityGmlParser.parsedObjects=Modell mit {} Objekten gelesen +CityGmlWriterUtils.unknownADEError= Fehler {} kann nicht zu einem ADE-Fehler konvertiert werden. Fehler wird nicht ausgegeben +CityGmlZipArchive.generalException=Unerwarteter Fehler beim Einlesen des ZIP-Archivs +CityGmlZipArchive.ioError=Zugriff auf ZIP-Datei fehlgeschlagen +CityGmlZipArchive.malformedZipFile=Einlesen des ZIP-Archivs abgebrochen, ZIP-Datei ist fehlerhaft! +DatabaseHandler.batchCommitFailure=Batch-commit abgebrochen: Auftreten eines kritischen Fehlers beim Versuch CityObject {} in die Datenbank zu schreiben! +DatabaseHandler.connectionFailure=Verbindung zur eingebetteten Datenbank konnte nicht hergestellt werden! +DatabaseHandler.fetchErrorIdsFailure=Abfragen der Liste von CityObjects mit Fehlern ist fehlgeschlagen! +DatabaseHandler.getAllCityObjectsFailure=Abfragen der Liste aller CityObjects ist fehlgeschlagen! +DatabaseHandler.getBBoxIntersectFailure=Verbindung zur Datenbank konnte nicht hergestellt werden, abfragen der BoundingBox-\u00dcberschneidungen von CityObject {} fehlgeschlagen! +DatabaseHandler.getBufferIntersectFailure=Verbindung zur Datenbank konnte nicht hergestellt werden, abfragen der Buffer-\u00dcberschneidungen von CityObject {} fehlgeschlagen! +DatabaseHandler.getFeatureCountFailure=Verbindung zur Datenbank konnte nicht hergestellt werden, abfragen der Anzahl an CityObjects fehlgeschlagen! +DatabaseHandler.marshallingFailure=Schreiben des CityObject {} in die Datenbank fehlgeschlagen! +DatabaseHandler.serializationFailure=Serialisierung des CityObject {} fehlgeschlagen! +DatabaseHandler.setupFailure=KRITISCHER FEHLER: Erstellen der eingebetteten Datenbank fehlgeschlagen! +DatabaseHandler.tableFailure=KRITISCHER FEHLER: Erstellen der "features" Tabelle fehlgeschlagen! +DatabaseHandler.unmarshallingFailure=Laden des CityObject {} aus der Datenbank fehlgeschlagen! +DistanceError.distanceFromPlane=Abstand von der Ebene +ErrorItemVisitor.childId=Kind ID +ErrorItemVisitor.component=Komponente +ErrorItemVisitor.degeneratedRing=Degenerierter Ring +ErrorItemVisitor.deviation=Abweichung +ErrorItemVisitor.distance=Distanz +ErrorItemVisitor.intersection=Verschneidung +ErrorItemVisitor.nameOfAttribute=Name des Attributs +ErrorItemVisitor.pointTouchesEdge=Punkt ber\u00fchrt Kante +ErrorItemVisitor.triangles=Dreiecke ExceptionDialog.stacktrace=Der Stacktrace des Fehlers war: -FilterPane.buildings=Geb\u00e4ude +FeatureMapper.polygonUnreferenced=Polygon {} wurde referenziert, konnte aber nicht gefunden werden! FilterPane.bridges=Br\u00fccken +FilterPane.buildings=Geb\u00e4ude FilterPane.landUse=Landnutzung FilterPane.transportation=Transport FilterPane.vegetation=Vegetation FilterPane.water=Wasser -MainToolBar.wireframe=Zeige/Verstecke Gitternetz -MainToolBar.culling=Aktiviere/Deaktiviere Entfernen der R\u00fcckseiten -MainToolBar.writeReports=Schreibe Reports +GeometryMapper.emptyPolygon=Polygon ohne externen Ring gefunden. Polygon wird ignoriert +LibraryObject.fileMissing=Die ImplicitGeometry eines Features verweist auf eine nicht vorhandene LibraryObject-Datei {} +LibraryObject.parsingError=LibraryObject-Datei {} konnte aufgrund eines Fehlers nicht ausgelesen werden +MainToolBar.culling=Aktiviere/Deaktiviere Entfernen der Polygon-R\u00fcckseiten MainToolBar.executeChecks=F\u00fchre Pr\u00fcfungen aus -MainToolBar.showWorld=Gesamtes Stadtmodell anzeigen -MainToolBar.resetCamera=Ansicht zur\u00fccksetzen -MainToolBar.hideRoof=Zeige/Verstecke Dach BoundarySurfaces +MainToolBar.hideRoof=Zeige/Verstecke Dach-BoundarySurfaces +MainToolBar.resetCamera=Kamera-Ansicht zur\u00fccksetzen +MainToolBar.showWorld=Zeige gesamtes Stadtmodell an +MainToolBar.wireframe=Aktiviere/Deaktiviere Gitternetz-Modus +MainToolBar.writeReports=Schreibe Berichte MainToolBar.zip=Zip-eintrag Auswahlfenster \u00f6ffnen -MainWindow.missingConfig=Konnte Konfigurationsdatei nicht finden. -MainWindow.loadGivenFile=Lade vorhandene Datei, bitte warten -MainWindow.finishedLoading=Fertig geladen -MainWindow.checking=Pr\u00fcfe, bitte warten -MainWindow.writeXml=Schreibe Xml Report -MainWindow.finishedXml=Xml Report abgeschlossen -MainWindow.writePdf=Schreibe Pdf Report -MainWindow.finishedPdf=Pdf Report abgeschlossen -MainWindow.loadFailed=Konnte GML-Datei nicht laden: {} MainWindow.all=Alle -MainWindow.withErrors=Mit Fehlern -MainWindow.export=Feature Exportieren +MainWindow.attributeTab=Attribute +MainWindow.availableLabel=Verf\u00fcgbar: +MainWindow.bridgeTab=Br\u00fccken +MainWindow.buildingsTab=Geb\u00e4ude +MainWindow.checking=Pr\u00fcfe, bitte warten +MainWindow.cityfurnitureTab=Stadtm\u00f6bel +MainWindow.clearBtn=Leeren MainWindow.copyId=GML-ID kopieren MainWindow.delete=Feature L\u00f6schen -MainWindow.infoTopLevelExport=Export ist nur f\u00fcr Featureobjekt basis m\u00f6glich! +MainWindow.edgesTab=Kanten +MainWindow.errorsTab=Fehler +MainWindow.export=Feature Exportieren +MainWindow.finishedLoading=Fertig geladen +MainWindow.finishedPdf=Pdf-Bericht abgeschlossen +MainWindow.finishedXml=Xml-Bericht abgeschlossen +MainWindow.focusCityObject=Objekt fokussieren +MainWindow.globalErrorsTab=Globale Fehler MainWindow.infoTopLevelCopyID=GML-ID kann nur von Featureobjekt basis kopiert werden! -mainWindow.warnCopyIdFailed=Kopieren der ID fehlgeschlagen! -OpenFileDialog.select=W\u00e4hle CityGML Datei aus +MainWindow.infoTopLevelExport=Export ist nur f\u00fcr Featureobjekt basis m\u00f6glich! MainWindow.languageChange=Um die Spracheinstellung zu \u00fcbernehmen muss CityDoctor2 neugestartet werden. -MainWindow.buildingsTab=Geb\u00e4ude -MainWindow.vegetationTab=Vegetation -MainWindow.transportationTab=Verkehrsobjekte -MainWindow.tunnelTab=Tunnel -MainWindow.bridgeTab=Br\u00fccken -MainWindow.waterTab=Gew\u00e4sser -MainWindow.terrainTab=Gel\u00e4nde -MainWindow.cityfurnitureTab=Stadtm\u00f6bel +MainWindow.loadFailed=Konnte GML-Datei nicht laden: {} +MainWindow.loadGivenFile=Lade vorhandene Datei, bitte warten +MainWindow.logTab=Log +MainWindow.memoryLabel=Speicher: +MainWindow.missingConfig=Konnte Konfigurationsdatei nicht finden. MainWindow.otherObjectsTab=Andere -MainWindow.viewLabel=Ansicht -MainWindow.showLabel=Zeige: -MainWindow.searchLabel=Suche: -MainWindow.searchBtn=Suche -MainWindow.clearBtn=Leeren -MainWindow.errorsTab=Fehler MainWindow.polygonsTab=Polygone -MainWindow.edgesTab=Kanten +MainWindow.searchBtn=Suche +MainWindow.searchLabel=Suche: +MainWindow.showLabel=Zeige: +MainWindow.terrainTab=Gel\u00e4nde +MainWindow.transportationTab=Verkehrsobjekte +MainWindow.tunnelTab=Tunnel +MainWindow.vegetationTab=Vegetation MainWindow.verticesTab=Punkte -MainWindow.attributeTab=Attribute -MainWindow.logTab=Log -MainWindow.globalErrorsTab=Globale Fehler -MainWindow.focusCityObject=Objekt fokussieren +MainWindow.viewLabel=Ansicht +MainWindow.warnCopyIdFailed=Kopieren der ID fehlgeschlagen! +MainWindow.waterTab=Gew\u00e4sser +MainWindow.withErrors=Mit Fehlern +MainWindow.writePdf=Schreibe Pdf-Bericht +MainWindow.writeXml=Schreibe Xml-Bericht +OpenFileDialog.cancelBtn=Abbrechen OpenFileDialog.fileLabel=Datei: -OpenFileDialog.selectBtn=Ausw\u00e4hlen OpenFileDialog.loadBtn=Laden +OpenFileDialog.loadFailed=Konnte CityGML Datei nicht laden +OpenFileDialog.lowMemoryLabel=Reduzierter Speicherverbrauchsmodus +OpenFileDialog.roundingPlacesLabel=Anzahl der Rundungsstellen +OpenFileDialog.select=W\u00e4hle CityGML Datei aus +OpenFileDialog.selectBtn=Ausw\u00e4hlen OpenFileDialog.settingsPane=Parser Einstellungen -OpenFileDialog.roundingPlacesLabel=NumberOfRoundingPlaces OpenFileDialog.xmlValidationLabel=F\u00fchre XML-Validierung aus -Checker.failXml=Konnte XML Fehlerbericht nicht schreiben. -Checker.failPdf=Konnte PDF Fehlerbericht nicht schreiben. -Checker.checksFinished=Pr\u00fcfungen beendet -Checker.schematronValidation=Starte Schematron Pr\u00fcfung -Checker.finishedSchematron=Schematron Pr\u00fcfung abgeschlossen -Checker.failReports=Konnte Pr\u00fcfberichte nicht schreiben. -Checker.checkFeature=Pr\u00fcfe Feature: {} -Checker.executeCheck=F\u00fchre Pr\u00fcfung aus: {} -ValidationConfiguration.reenable={} ist deaktiviert wird aber von {} ben\u00f6tigt, reaktiviere +TimeFormatter.hours={0} Stunden +TimeFormatter.lessThanASecond=< 1 Sekunde +TimeFormatter.minutes={0} Minuten +TimeFormatter.oneHour=1 Stunde +TimeFormatter.oneMinute=1 Minute +TimeFormatter.oneSecond=1 Sekunde +TimeFormatter.seconds={0} Sekunden +Unit.Degree=Grad +Unit.Radian=Radiant ValidationConfiguration.missingSchematron={} existiert nicht, deaktiviere Schematron Pr\u00fcfung -CheckContainer.error=Unerwarteter Fehler bei der Ausf\u00fchrung von Pr\u00fcfung: {} -Checks.missingCheck=Konnte keine Pr\u00fcfung f\u00fcr id {} finden -OpenFileDialog.cancelBtn=Abbrechen -CheckDialog.checksTab=Pr\u00fcfungen -CheckDialog.filterTab=Filter -CheckDialog.globalParametersLabel=Globale Parameter -CheckDialog.availableChecksLabel=Verf\u00fcgbare Pr\u00fcfungen -CheckDialog.geometricChecksLabel=Geometrische Pr\u00fcfungen -CheckDialog.semanticChecksLabel=Semantische Pr\u00fcfungen -CheckDialog.schematronFileLabel=Schematron Datei -CheckDialog.selectBtn=Ausw\u00e4hlen -CheckDialog.checkBtn=Pr\u00fcfen -CheckDialog.cancelBtn=Abbrechen -CheckDialog.streamCheckOption=Niedrigen Arbeitsspeicherverbrauchsmodus aktivieren -CheckDialog.streamCheckLabel=Stadtmodelle werden nicht in den Arbeitsspeicher geladen. Ergebnisse werden in der QualityADE in Kopien der Eingangsdateien gespeichert. -CheckDialog.outputPathLabel=Ausgabeordner (Pflichtfeld): -CheckDialog.outputPathBtn=Ausw\u00e4hlen -CheckDialog.pdfReportsOption=PDF Berichte erstellen -CheckDialog.xmlReportsOption=XML Berichte erstellen -CheckDialog.noPathError=Ausgabepfad wurde nicht gesetzt! -ZipEntryManager.title=Zipeintrag Manager -ZipEntryManager.entryListTitle=Zipeintr\u00e4ge -ZipEntryManager.metadata=Metadaten -ZipEntryManager.subpathLbl=Unterpfad: -ZipEntryManager.erroneousLbl=Fehlerhaft: -ZipEntryManager.excessiveFileSize=Datei zu gro\u00DF -ZipEntryManager.invalidCityGml=Ung\u00fcltige CityGML Datei -ZipEntryManager.ioError=Dateizugriff fehlgeschlagen -ZipEntryManager.filesizeLbl=Dateigr\u00f6\u00DFe: -ZipEntryManager.validatedLbl=Validiert: -ZipEntryManager.objectCountLbl=Objektanzahl: -ZipEntryManager.loadBtn=CityGML Modell laden -ZipEntryManager.decompressBtn=Datei entpacken -ZipEntryManager.decompressAllBtn=Alle Dateien entpacken -ZipEntryManager.checkAllBtn=Alle Dateien pr\u00fcfen -ZipEntryManager.showReportBtn=Fehlerstatistik anzeigen -ZipEntryManager.saveBtn=Validierungsergebnisse exportieren -ZipEntryManager.cancelBtn=Abbruch -ZipEntryManager.unknownValue=Unbekannt -ZipEntryManager.yes=Ja -ZipEntryManager.no=Nein -CityGmlZipArchive.ioError=Zugriff auf ZIP-Datei fehlgeschlagen -CityGmlZipArchive.malformedZipFile=Einlesen des ZIP-Archivs abgebrochen, ZIP-Datei ist fehlerhaft! -CityGmlZipArchive.generalException=Unerwarteter Fehler beim Einlesen des ZIP-Archivs -WriteReportDialog.writeBtn=Speichern +ValidationConfiguration.reenable={} ist deaktiviert wird aber von {} ben\u00f6tigt, reaktiviere WriteReportDialog.cancelBtn=Abbrechen WriteReportDialog.errorStatisticsLabel=Fehler Statistik WriteReportDialog.saveImageBtn=Bild Speichern WriteReportDialog.selectPdfBtn=Ausw\u00e4hlen WriteReportDialog.selectXmlFile=Ausw\u00e4hlen +WriteReportDialog.writeBtn=Speichern WriteReportDialog.xAxisLabel=Fehler -WriteReportDialog.yAxisLabel=Anzahl -Unit.Radian=Radiant -Unit.Degree=Grad -FeatureMapper.polygonUnreferenced=Polygon {} ist referenziert, konnte aber nicht gefunden werden -GeometryMapper.emptyPolygon=Polygon ohne externen Ring gefunden, ignoriere -CityGmlParser.parsedObjects=Modell mit {} Objekten gelesen -CityGmlParser.chunkReadFailed=Konnte Datei nicht in St\u00fccken lesen, versuche komplett zu lesen -CityGmlParser.notValidGmlFile=Dies ist keine korrekte CityGML Datei\n -CityGmlParser.errorReadingGmlFile=Fehler beim lesen der CityGML Datei\n{} -CityGmlParser.errorWritingGmlFile=Fehler beim schreiben der CityGML Datei\n{} -CityGmlParser.noConversionNeeded=Koordinatensystem in Metern, keine Konvertierung notwendig -CityGmlParser.failedEPSGParse=Lesen des EPSG Codes fehlgeschlagen, greife auf metrisches System zur\u00fcck -CityGmlParser.missingEPSGCode=Kein EPSG Code gefunden, nehme metrisches System an -OpenFileDialog.loadFailed=Konnte CityGML Datei nicht laden -MainWindow.memoryLabel=Speicher: -CheckDialog.checksReenabledAlert=Manche Pr\u00fcfungen wurden reaktiviert damit andere gewollte Pr\u00fcfungen durchgef\u00fchrt werden k\u00f6nnen\nMehr Details sind im Log geschrieben -MainWindow.availableLabel=Verf\u00fcgbar: -OpenFileDialog.lowMemoryLabel=Reduzierter Speicherverbrauchsmodus -ErrorItemVisitor.intersection=Verschneidung -ErrorItemVisitor.component=Komponente -ErrorItemVisitor.nameOfAttribute=Name des Attributs -ErrorItemVisitor.childId=Kind ID -ErrorItemVisitor.distance=Distanz -ErrorItemVisitor.pointTouchesEdge=Punkt ber\u00fchrt Kante -ErrorItemVisitor.degeneratedRing=Degenerierter Ring -ErrorItemVisitor.deviation=Abweichung -ErrorItemVisitor.triangles=Dreiecke \ No newline at end of file +WriteReportDialog.yAxisLabel=Anzahl \ No newline at end of file diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/log4j2.xml b/CityDoctorParent/CityDoctorModel/src/main/resources/log4j2.xml index 4e951d6be8c184c776c0a02290cc32671d09c3de..d398aaaa8f5b4f31148c1c39d67d47b85690b9d9 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/resources/log4j2.xml +++ b/CityDoctorParent/CityDoctorModel/src/main/resources/log4j2.xml @@ -14,5 +14,8 @@ + + + \ No newline at end of file diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDataBaseHandlerTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDataBaseHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..06c0bb6e713a27cd1593503520cc2005905d776b --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDataBaseHandlerTest.java @@ -0,0 +1,244 @@ +package de.hft.stuttgart.citydoctor2.database; + +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon; +import de.hft.stuttgart.citydoctor2.datastructure.Geometry; +import de.hft.stuttgart.citydoctor2.datastructure.GeometryTestUtils; +import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; +import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; +import de.hft.stuttgart.citydoctor2.datastructure.Lod; +import de.hft.stuttgart.citydoctor2.datastructure.Vertex; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; +import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; +import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; +import org.citygml4j.core.model.building.AbstractBuilding; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.List; + +import static de.hft.stuttgart.citydoctor2.database.SerializationTest.assertCityObjectEquality; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +public class EmbeddedDataBaseHandlerTest { + + private EmbeddedDatabaseHandler handler; + + @Before + public void resetDatabase() { + try { + handler = new EmbeddedDatabaseHandler(); + handler.setupFeaturesTable(); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + + @Test + public void testGetBboxIntersectingObjects() { + Building b = new Building(); + Building b2 = new Building(); + b2.setGmlObject(Mockito.mock(AbstractBuilding.class)); + Building b3 = new Building(); + Building b4 = new Building(); + b4.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID, Lod.LOD0)); + + Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0, Geometry.Orientation.OUTWARD); + ConcretePolygon polygon = new ConcretePolygon(); + geom.getPolygons().add(polygon); + polygon.setParent(geom); + LinearRing lr = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + polygon.setExteriorRing(lr); + Vertex v1 = new Vertex(10, 10, 8); + lr.getVertices().add(v1); + Vertex v2 = new Vertex(14, 15, 7); + lr.getVertices().add(v2); + Vertex v3 = new Vertex(14, 15, 3); + lr.getVertices().add(v3); + Vertex v4 = new Vertex(10, 10, 3); + lr.getVertices().add(v4); + lr.getVertices().add(v1); + geom.updateEdgesAndVertices(); + b.addGeometry(geom); + + + Geometry geom2 = new Geometry(GeometryType.SOLID, Lod.LOD0, Geometry.Orientation.OUTWARD); + ConcretePolygon polygon2 = new ConcretePolygon(); + geom2.getPolygons().add(polygon2); + polygon2.setParent(geom2); + LinearRing lr2 = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + polygon2.setExteriorRing(lr2); + Vertex v1b2 = new Vertex(6, 6, 8); + lr2.getVertices().add(v1b2); + Vertex v2b2 = new Vertex(11, 13, 7); + lr2.getVertices().add(v2b2); + Vertex v3b2 = new Vertex(11, 13, 3); + lr2.getVertices().add(v3b2); + Vertex v4b2 = new Vertex(6, 6, 3); + lr2.getVertices().add(v4b2); + lr2.getVertices().add(v1b2); + geom2.updateEdgesAndVertices(); + b2.addGeometry(geom2); + + Geometry geom3 = new Geometry(GeometryType.SOLID, Lod.LOD0, Geometry.Orientation.OUTWARD); + ConcretePolygon polygon3 = new ConcretePolygon(); + geom3.getPolygons().add(polygon3); + polygon3.setParent(geom3); + LinearRing lr3 = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + polygon3.setExteriorRing(lr3); + Vertex v1b3 = new Vertex(6, 6, 8); + lr3.getVertices().add(v1b3); + Vertex v2b3 = new Vertex(10, 9.999, 7); + lr3.getVertices().add(v2b3); + Vertex v3b3 = new Vertex(10, 9.999, 3); + lr3.getVertices().add(v3b3); + Vertex v4b3 = new Vertex(6, 6, 3); + lr3.getVertices().add(v4b3); + lr3.getVertices().add(v1b3); + geom3.updateEdgesAndVertices(); + b3.addGeometry(geom3); + + handler.marshallCityObject(b); + handler.marshallCityObject(b2); + handler.marshallCityObject(b3); + handler.marshallCityObject(b4); + assertEquals(4, handler.getFeatureCount()); + + List objects = handler.getGeometryCollisionCandidates(b); + assertEquals(1, objects.size()); + assertEquals(4, handler.getFeatureCount()); + + CityObject co = handler.unmarshallCityObject(objects.get(0)); + assertNotNull(co); + assertCityObjectEquality(b2, co); + + } + + @Test + public void testGetBboxBufferIntersectingObjects() { + Building b = new Building(); + Building b2 = new Building(); + b2.setGmlObject(Mockito.mock(AbstractBuilding.class)); + Building b3 = new Building(); + Building b4 = new Building(); + b4.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID, Lod.LOD0)); + + + Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD0, Geometry.Orientation.OUTWARD); + ConcretePolygon polygon = new ConcretePolygon(); + geom.getPolygons().add(polygon); + polygon.setParent(geom); + LinearRing lr = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + polygon.setExteriorRing(lr); + Vertex v1 = new Vertex(10, 10, 8); + lr.getVertices().add(v1); + Vertex v2 = new Vertex(14, 15, 7); + lr.getVertices().add(v2); + Vertex v3 = new Vertex(14, 15, 3); + lr.getVertices().add(v3); + Vertex v4 = new Vertex(10, 10, 3); + lr.getVertices().add(v4); + lr.getVertices().add(v1); + geom.updateEdgesAndVertices(); + b.addGeometry(geom); + + + Geometry geom2 = new Geometry(GeometryType.SOLID, Lod.LOD0, Geometry.Orientation.OUTWARD); + ConcretePolygon polygon2 = new ConcretePolygon(); + geom2.getPolygons().add(polygon2); + polygon2.setParent(geom2); + LinearRing lr2 = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + polygon2.setExteriorRing(lr2); + Vertex v1b2 = new Vertex(6, 6, 8); + lr2.getVertices().add(v1b2); + Vertex v2b2 = new Vertex(9, 9, 7); + lr2.getVertices().add(v2b2); + Vertex v3b2 = new Vertex(9, 9, 3); + lr2.getVertices().add(v3b2); + Vertex v4b2 = new Vertex(6, 6, 3); + lr2.getVertices().add(v4b2); + lr2.getVertices().add(v1b2); + geom2.updateEdgesAndVertices(); + b2.addGeometry(geom2); + + Geometry geom3 = new Geometry(GeometryType.SOLID, Lod.LOD0, Geometry.Orientation.OUTWARD); + ConcretePolygon polygon3 = new ConcretePolygon(); + geom3.getPolygons().add(polygon3); + polygon3.setParent(geom3); + LinearRing lr3 = new LinearRing(LinearRing.LinearRingType.EXTERIOR); + polygon3.setExteriorRing(lr3); + Vertex v1b3 = new Vertex(4, 4, 8); + lr3.getVertices().add(v1b3); + Vertex v2b3 = new Vertex(8.999, 8.999, 7); + lr3.getVertices().add(v2b3); + Vertex v3b3 = new Vertex(8.999, 8.999, 3); + lr3.getVertices().add(v3b3); + Vertex v4b3 = new Vertex(4, 4, 3); + lr3.getVertices().add(v4b3); + lr3.getVertices().add(v1b3); + geom3.updateEdgesAndVertices(); + b3.addGeometry(geom3); + + handler.marshallCityObject(b); + handler.marshallCityObject(b2); + handler.marshallCityObject(b3); + handler.marshallCityObject(b4); + assertEquals(4, handler.getFeatureCount()); + + List objects = handler.getBufferCollisionCandidates(b, Math.sqrt(2)); + assertEquals(1, objects.size()); + assertEquals(4, handler.getFeatureCount()); + + CityObject co = handler.unmarshallCityObject(objects.get(0)); + assertNotNull(co); + assertCityObjectEquality(b2, co); + + } + + @Test + public void testMarshallingRoundTripSimpleSolid() throws InvalidGmlFileException, CityGmlParseException { + ParserConfiguration config = new ParserConfiguration(8, false); + CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/SimpleSolid_SrefBS.gml", config); + + Building b = model.getBuildings().toList().get(0); + assertNotNull(b); + handler.marshallCityObject(b); + assertEquals(1, handler.getFeatureCount()); + + CityObject b2 = handler.unmarshallCityObject(b.getGmlId()); + assertNotNull(b2); + assertEquals(1, handler.getFeatureCount()); + + assertCityObjectEquality(b, b2); + + } + + + @Test + public void testMarshallingRoundTripFzk() throws InvalidGmlFileException, CityGmlParseException { + ParserConfiguration config = new ParserConfiguration(8, false); + CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/FZK_haus.gml", config); + + Building b = model.getBuildings().toList().get(0); + assertNotNull(b); + assertEquals(1, handler.getFeatureCount()); + handler.marshallCityObject(b); + assertEquals(1, handler.getFeatureCount()); + + CityObject b2 = handler.unmarshallCityObject(b.getGmlId()); + assertNotNull(b2); + assertEquals(1, handler.getFeatureCount()); + + assertCityObjectEquality(b, b2); + + } + +} diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/FeatureCacheTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/FeatureCacheTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b17640f6d451cfda19f802703dba394ce570e27c --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/FeatureCacheTest.java @@ -0,0 +1,99 @@ +package de.hft.stuttgart.citydoctor2.database; + +import de.hft.stuttgart.citydoctor2.datastructure.*; +import org.citygml4j.core.model.building.AbstractBuilding; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.mock; + +public class FeatureCacheTest { + + + + @Test + public void testPut(){ + FeatureCache cache = new FeatureCache(); + + Building b = new Building(); + b.setGmlObject(mock(AbstractBuilding.class)); + b.setGmlId(new GmlId("test")); + b.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID, Lod.LOD0)); + + assertEquals(0, cache.getTotalFeatureCount()); + cache.put(b); + cache.synchronize(); + + assertEquals(1, cache.getTotalFeatureCount()); + } + + @Test + public void testGet(){ + FeatureCache cache = new FeatureCache(); + + assertNull(cache.get(new GmlId("test"))); + Building b = new Building(); + + b.setGmlObject(mock(AbstractBuilding.class)); + b.setGmlId(new GmlId("test")); + b.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID, Lod.LOD0)); + assertEquals(0, cache.getTotalFeatureCount()); + cache.put(b); + cache.synchronize(); + + CityObject b2 = cache.get(new GmlId("test")); + assertEquals(b.getGmlId(), b2.getGmlId()); + } + + @Test + public void testStateHandlingFromIdle(){ + FeatureCache cache = new FeatureCache(); + assertEquals(FeatureCache.CacheState.IDLE, cache.getState()); + + AutoCloseable parsingContext = cache.startParsingMode(); + try(parsingContext){ + assertEquals(FeatureCache.CacheState.PARSING, cache.getState()); + } catch (Exception e){ + throw new RuntimeException(e); + } + assertEquals(FeatureCache.CacheState.IDLE, cache.getState()); + + AutoCloseable checkingContext = cache.startCheckingMode(); + try(checkingContext){ + assertEquals(FeatureCache.CacheState.CHECKING, cache.getState()); + } catch (Exception e){ + throw new RuntimeException(e); + } + assertEquals(FeatureCache.CacheState.IDLE, cache.getState()); + } + + @Test + public void testCheckingModeStateCollision(){ + FeatureCache cache = new FeatureCache(); + assertEquals(FeatureCache.CacheState.IDLE, cache.getState()); + AutoCloseable checkingContext = cache.startCheckingMode(); + try(checkingContext){ + assertEquals(FeatureCache.CacheState.CHECKING, cache.getState()); + assertThrows(IllegalStateException.class, cache::startParsingMode); + } catch (Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testParsingModeStateCollision(){ + FeatureCache cache = new FeatureCache(); + assertEquals(FeatureCache.CacheState.IDLE, cache.getState()); + AutoCloseable parsingContext = cache.startParsingMode(); + try(parsingContext){ + assertEquals(FeatureCache.CacheState.PARSING, cache.getState()); + assertThrows(IllegalStateException.class, cache::startCheckingMode); + } catch (Exception e){ + throw new RuntimeException(e); + } + } + + +} diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/SerializationTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/SerializationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d664d6603d6ebd22f8290c440253a4589fb820ae --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/database/SerializationTest.java @@ -0,0 +1,59 @@ +package de.hft.stuttgart.citydoctor2.database; + +import de.hft.stuttgart.citydoctor2.datastructure.Building; +import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; +import de.hft.stuttgart.citydoctor2.datastructure.CityObject; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; +import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; +import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; +import de.hft.stuttgart.citydoctor2.utils.visitors.CityObjectCollector; +import org.apache.commons.lang3.SerializationUtils; +import org.junit.Test; + +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class SerializationTest { + + static void assertCityObjectEquality(CityObject c1, CityObject c2) { + assertEquals(c1.getGmlId(), c2.getGmlId()); + assertEquals(c1.getFeatureType(), c2.getFeatureType()); + assertEquals(c1.getGmlObject().getId(), c2.getGmlObject().getId()); + + CityObjectCollector collector = new CityObjectCollector(); + c1.accept(collector); + Set coB = collector.getCityObjects(); + collector = new CityObjectCollector(); + c2.accept(collector); + Set coB2 = collector.getCityObjects(); + assertEquals(coB.size(), coB2.size()); + } + + @Test + public void testRoundtripSimpleSolid() throws CityGmlParseException, InvalidGmlFileException { + ParserConfiguration config = new ParserConfiguration(8, false); + CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/SimpleSolid_SrefBS.gml", config); + Building b = model.getBuildings().toList().get(0); + assertNotNull(b); + Building b2 = SerializationUtils.roundtrip(b); + assertNotNull(b2); + + assertCityObjectEquality(b, b2); + } + + + @Test + public void testRoundtripFzk() throws CityGmlParseException, InvalidGmlFileException { + ParserConfiguration config = new ParserConfiguration(8, false); + CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/FZK_haus.gml", config); + Building b = model.getBuildings().toList().get(0); + assertNotNull(b); + Building b2 = SerializationUtils.roundtrip(b); + + assertCityObjectEquality(b, b2); + } + +} diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurfaceTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurfaceTest.java index 1275cc857af29974dfcd4e6a959f63b7c3297f82..c08b1ad7cede13dbb1522e5bcab5081630b9564d 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurfaceTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BoundarySurfaceTest.java @@ -51,11 +51,9 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; public class BoundarySurfaceTest { - //Todo: Check this class for rework potential with the new Visitors - @Test public void testVisitorPropagation() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); Opening oMock = Mockito.mock(Opening.class); bs.addOpening(oMock); @@ -68,7 +66,7 @@ public class BoundarySurfaceTest { @Test public void testAccept() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); Opening oMock = Mockito.mock(Opening.class); bs.addOpening(oMock); AtomicInteger bsCounter = new AtomicInteger(0); @@ -86,7 +84,7 @@ public class BoundarySurfaceTest { @Test public void testAcceptWithoutFittingCheck() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); Opening oMock = Mockito.mock(Opening.class); bs.addOpening(oMock); AtomicInteger bsCounter = new AtomicInteger(0); @@ -104,7 +102,7 @@ public class BoundarySurfaceTest { @Test public void testPrepareForChecking() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2, Orientation.OUTWARD); Geometry spyGeom = Mockito.spy(geom); bs.addGeometry(spyGeom); @@ -114,7 +112,7 @@ public class BoundarySurfaceTest { @Test public void testContainsError() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); assertFalse(bs.containsError(CheckId.C_GE_P_HOLE_OUTSIDE)); bs.addCheckResult( new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, Mockito.mock(CheckError.class))); @@ -124,9 +122,9 @@ public class BoundarySurfaceTest { @Test public void testContainsErrorInOpening() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); assertFalse(bs.containsError(CheckId.C_GE_P_HOLE_OUTSIDE)); - Opening o = new Opening(OpeningType.WINDOW, SurfaceFeatureType.BUILDING, bs, null); + Opening o = new Opening(OpeningType.WINDOW, bs, null); bs.addOpening(o); o.addCheckResult( new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, Mockito.mock(CheckError.class))); @@ -136,7 +134,7 @@ public class BoundarySurfaceTest { @Test public void testClearAllContainedCheckResults() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); Opening oMock = Mockito.mock(Opening.class); bs.addCheckResult( new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, Mockito.mock(CheckError.class))); @@ -149,7 +147,7 @@ public class BoundarySurfaceTest { @Test public void testContainsAnyError() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); assertFalse(bs.containsAnyError()); bs.addCheckResult( new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, Mockito.mock(CheckError.class))); @@ -159,19 +157,18 @@ public class BoundarySurfaceTest { @Test public void testCollectContainedErrors() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); bs.addCheckResult( new CheckResult(CheckId.C_GE_P_HOLE_OUTSIDE, ResultStatus.ERROR, Mockito.mock(CheckError.class))); List errors = new ArrayList<>(); bs.collectContainedErrors(errors); assertEquals(1, errors.size()); - ; } @Test public void testReCreateGeometriesWithoutId() { WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); assertNotNull(ws.getId()); } @@ -180,7 +177,7 @@ public class BoundarySurfaceTest { public void testReCreateGeometriesWithId() { WallSurface ws = new WallSurface(); ws.setId("test"); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); // nothing has changed assertEquals("test", ws.getId()); @@ -190,89 +187,52 @@ public class BoundarySurfaceTest { } @Test - public void testReCreateGeometriesMultiSurfaceLod2() { - WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE)); - bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); - assertNotNull(ws.getLod2MultiSurface()); - assertNull(ws.getLod3MultiSurface()); - assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - } - - @Test - public void testReCreateGeometriesMultiSurfaceBridgeLod2() { - WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BRIDGE, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE)); - bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); - assertNotNull(ws.getLod2MultiSurface()); - assertNull(ws.getLod3MultiSurface()); - assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - } - - @Test - public void testReCreateGeometriesMultiSurfaceBridgeLod3() { + public void testReCreateGeometriesMultiSurfaceLod0() { WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BRIDGE, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD3)); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); + bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD0)); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); + assertNotNull(ws.getLod0MultiSurface()); + assertNull(ws.getLod1MultiSurface()); assertNull(ws.getLod2MultiSurface()); - assertNotNull(ws.getLod3MultiSurface()); + assertNull(ws.getLod3MultiSurface()); assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); } @Test - public void testReCreateGeometriesMultiSurfaceBridgeLod4() { + public void testReCreateGeometriesMultiSurfaceLod1() { WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BRIDGE, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD4)); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); + bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD1)); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); + assertNull(ws.getLod0MultiSurface()); + assertNotNull(ws.getLod1MultiSurface()); assertNull(ws.getLod2MultiSurface()); assertNull(ws.getLod3MultiSurface()); - assertNotNull(ws.getDeprecatedProperties().getLod4MultiSurface()); + assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); } @Test - public void testReCreateGeometriesMultiSurfaceTunnelLod2() { + public void testReCreateGeometriesMultiSurfaceLod2() { WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE)); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); + assertNull(ws.getLod0MultiSurface()); + assertNull(ws.getLod1MultiSurface()); assertNotNull(ws.getLod2MultiSurface()); assertNull(ws.getLod3MultiSurface()); assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); } - @Test - public void testReCreateGeometriesMultiSurfaceTunnelLod3() { - WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD3)); - bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); - assertNull(ws.getLod2MultiSurface()); - assertNotNull(ws.getLod3MultiSurface()); - assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - } - - @Test - public void testReCreateGeometriesMultiSurfaceTunnelLod4() { - WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD4)); - bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); - assertNull(ws.getLod2MultiSurface()); - assertNull(ws.getLod3MultiSurface()); - assertNotNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - } - @Test public void testReCreateGeometriesMultiSurfaceLod3() { WallSurface ws = new WallSurface(); - ws.setId("test"); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface( BoundarySurfaceType.WALL, ws); bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD3)); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); + assertNull(ws.getLod0MultiSurface()); + assertNull(ws.getLod1MultiSurface()); assertNull(ws.getLod2MultiSurface()); assertNotNull(ws.getLod3MultiSurface()); assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); @@ -281,30 +241,21 @@ public class BoundarySurfaceTest { @Test public void testReCreateGeometriesMultiSurfaceLod4() { WallSurface ws = new WallSurface(); - ws.setId("test"); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD4)); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); + assertNull(ws.getLod0MultiSurface()); + assertNull(ws.getLod1MultiSurface()); assertNull(ws.getLod2MultiSurface()); assertNull(ws.getLod3MultiSurface()); assertNotNull(ws.getDeprecatedProperties().getLod4MultiSurface()); } - @Test - public void testReCreateGeometriesMultiSurfaceLod0() { - WallSurface ws = new WallSurface(); - ws.setId("test"); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); - bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD0)); - bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); - assertNotNull(ws.getLod0MultiSurface()); - } @Test(expected = IllegalStateException.class) public void testReCreateGeometriesSolid() { WallSurface ws = new WallSurface(); - ws.setId("test"); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); bs.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID)); bs.reCreateGeometries(GeometryFactory.newInstance(), new ParserConfiguration(8, false)); } @@ -312,8 +263,7 @@ public class BoundarySurfaceTest { @Test public void testReCreateGeometriesOpenings() { WallSurface ws = new WallSurface(); - ws.setId("test"); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); Opening oMock = Mockito.mock(Opening.class); bs.addOpening(oMock); GeometryFactory factory = GeometryFactory.newInstance(); @@ -325,7 +275,7 @@ public class BoundarySurfaceTest { @Test public void testGetGmlObject() { WallSurface ws = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); assertEquals(ws, bs.getGmlObject()); } @@ -338,7 +288,7 @@ public class BoundarySurfaceTest { assertNotNull(ws.getLod2MultiSurface()); assertNotNull(ws.getLod3MultiSurface()); assertNotNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, ws); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, ws); Opening oMock = Mockito.mock(Opening.class); bs.addOpening(oMock); bs.accept(new UnsetGeometriesVisitor()); @@ -348,41 +298,9 @@ public class BoundarySurfaceTest { assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); } - @Test - public void testUnsetGmlGeometriesBridge() { - WallSurface ws = new WallSurface(); - ws.setLod2MultiSurface(new MultiSurfaceProperty()); - ws.setLod3MultiSurface(new MultiSurfaceProperty()); - ws.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty()); - assertNotNull(ws.getLod2MultiSurface()); - assertNotNull(ws.getLod3MultiSurface()); - assertNotNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BRIDGE, BoundarySurfaceType.WALL, ws); - bs.unsetGmlGeometries(); - assertNull(ws.getLod2MultiSurface()); - assertNull(ws.getLod3MultiSurface()); - assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - } - - @Test - public void testUnsetGmlGeometriesTunnel() { - WallSurface ws = new WallSurface(); - ws.setLod2MultiSurface(new MultiSurfaceProperty()); - ws.setLod3MultiSurface(new MultiSurfaceProperty()); - ws.getDeprecatedProperties().setLod4MultiSurface(new MultiSurfaceProperty()); - assertNotNull(ws.getLod2MultiSurface()); - assertNotNull(ws.getLod3MultiSurface()); - assertNotNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, ws); - bs.unsetGmlGeometries(); - assertNull(ws.getLod2MultiSurface()); - assertNull(ws.getLod3MultiSurface()); - assertNull(ws.getDeprecatedProperties().getLod4MultiSurface()); - } - @Test public void testGetFeatureType() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); assertEquals(FeatureType.BOUNDARY_SURFACE, bs.getFeatureType()); } @@ -392,17 +310,11 @@ public class BoundarySurfaceTest { BoundarySurface bs = new BoundarySurface(aco); assertEquals(aco, bs.getGmlObject()); } - - @Test - public void testSetFeatureType() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, null); - bs.setFeatureType(SurfaceFeatureType.BRIDGE); - assertEquals(SurfaceFeatureType.BRIDGE, bs.getSurfaceFeatureType()); - } + @Test public void testSetType() { - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.TUNNEL, BoundarySurfaceType.WALL, null); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, null); bs.setType(BoundarySurfaceType.ROOF); assertEquals(BoundarySurfaceType.ROOF, bs.getType()); } diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObjectTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObjectTest.java index d185d272673832131bfd175d24d84cb43161a643..931ce45c4daf8176200c0aa68071fbf85743c75b 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObjectTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BridgeObjectTest.java @@ -51,7 +51,6 @@ import de.hft.stuttgart.citydoctor2.utils.visitors.UnsetGeometriesVisitor; public class BridgeObjectTest { - //TODO: Rework this class with the new Visitors @Test public void testAccept() { diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingTest.java index a27eee4343fe5532d21b52b972e779275295417b..21d897faca604266bdf25a662d05ba0abc78a0ee 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingTest.java @@ -64,7 +64,7 @@ public class BuildingTest { b.setCityGmlBuilding(createCityGmlBuilding()); RoofSurface rs = new RoofSurface(); rs.setId("testRoof"); - BoundarySurface surface = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.ROOF, rs); + BoundarySurface surface = new BoundarySurface(BoundarySurfaceType.ROOF, rs); Geometry geomSurface = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2, Orientation.OUTWARD); geomSurface.addPolygon(new LinkedPolygon(p, geomSurface)); geomSurface.updateEdgesAndVertices(); @@ -75,7 +75,8 @@ public class BuildingTest { assertNotSame(b, copy); assertEquals(b.getGmlId(), copy.getGmlId()); - + + copy.prepareForChecking(); Geometry copyGeom = copy.getGeometries().get(0); assertNotSame(geom, copyGeom); diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModelTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModelTest.java index 7eeee2897303efc7f89d28f3d3431b98273c69a9..b535500a2481ebc4398d7568f6b7cb1219165ac1 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModelTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModelTest.java @@ -27,11 +27,14 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; +import de.hft.stuttgart.citydoctor2.database.FeatureCache; +import de.hft.stuttgart.citydoctor2.database.UnconnectedCache; import org.citygml4j.core.ade.ADEException; import org.citygml4j.core.model.CityGMLVersion; import org.citygml4j.core.model.core.AbstractFeatureProperty; import org.citygml4j.core.model.core.CityModel; import org.citygml4j.xml.writer.CityGMLWriteException; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -63,28 +66,40 @@ import de.hft.stuttgart.quality.model.types.ValidationPlan; public class CityDoctorModelTest { + private File mockFile; + private ParserConfiguration config; + private CityDoctorModel model; + private final FeatureCache featureCache = new FeatureCache(); + @Before + public void setUp(){ + mockFile = Mockito.mock(File.class); + Mockito.when(mockFile.getName()).thenReturn("test"); + config = new ParserConfiguration(8, false); + featureCache.resetCache(); + model = new CityDoctorModel(config, mockFile, featureCache); + } + @Rule public TemporaryFolder folder = new TemporaryFolder(); @Test(expected = IllegalArgumentException.class) public void testCityDoctorModelNoConfig() { - new CityDoctorModel(null, null); + new CityDoctorModel(null, mockFile, new UnconnectedCache()); + } + + @Test(expected = IllegalArgumentException.class) + public void testCityDoctorModelNoFile() { + new CityDoctorModel(config, null, new UnconnectedCache()); } @Test public void testSetValidated() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); model.setValidated(Mockito.mock(ValidationPlan.class)); assertTrue(model.isValidated()); } @Test public void testAddGlobalError() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); CheckError err = Mockito.mock(CheckError.class); model.addGlobalError(err); assertEquals(err, model.getGlobalErrors().get(0)); @@ -92,9 +107,6 @@ public class CityDoctorModelTest { @Test public void testAddGlobalErrors() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); CheckError err1 = Mockito.mock(CheckError.class); CheckError err2 = Mockito.mock(CheckError.class); List errors = new ArrayList<>(); @@ -107,19 +119,15 @@ public class CityDoctorModelTest { @Test public void testGetFile() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); - assertEquals(f, model.getFile()); + assertEquals(mockFile, model.getFile()); } @Test public void testCreateFeatureStream() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Building b = Mockito.mock(Building.class); + Mockito.when(b.getGmlId()).thenReturn(new GmlId("b")); Vegetation v = Mockito.mock(Vegetation.class); + Mockito.when(v.getGmlId()).thenReturn(new GmlId("v")); model.addBuilding(b); model.addVegetation(v); assertTrue(model.createFeatureStream().anyMatch(c -> c == b)); @@ -129,9 +137,6 @@ public class CityDoctorModelTest { @Test public void testSaveAsWithoutValidation() throws CityGMLWriteException, ADEException, IOException, CityGmlParseException, InvalidGmlFileException, CityDoctorWriteException { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); model.setParsedCityGMLVersion(CityGMLVersion.v2_0); CityModel cModel = new CityModel(); model.setCityModel(cModel); @@ -147,7 +152,7 @@ public class CityDoctorModelTest { assertTrue(saveFile.length() > 0); CityDoctorModel parsedModel = CityGmlParser.parseCityGmlFile(saveFile.getAbsolutePath(), config); - Building parsedBuilding = parsedModel.getBuildings().get(0); + Building parsedBuilding = parsedModel.getBuildings().toList().get(0); assertEquals("testId", parsedBuilding.getGmlId().getGmlString()); assertEquals(1, parsedBuilding.getGeometries().size()); } @@ -155,9 +160,7 @@ public class CityDoctorModelTest { @Test public void testSaveAsWithValidation() throws CityGMLWriteException, ADEException, IOException, CityGmlParseException, InvalidGmlFileException, CityDoctorWriteException { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); + model.setParsedCityGMLVersion(CityGMLVersion.v2_0); CityModel cModel = new CityModel(); ValidationPlan plan = new ValidationPlan(); @@ -214,7 +217,7 @@ public class CityDoctorModelTest { assertTrue(saveFile.length() > 0); CityDoctorModel parsedModel = CityGmlParser.parseCityGmlFile(saveFile.getAbsolutePath(), config); - Building parsedBuilding = parsedModel.getBuildings().get(0); + Building parsedBuilding = parsedModel.getBuildings().toList().get(0); assertEquals("testId", parsedBuilding.getGmlId().getGmlString()); assertEquals(1, parsedBuilding.getGeometries().size()); List props = parsedBuilding.getGmlObject().getADEProperties(CityObjectProperties.class); @@ -234,9 +237,6 @@ public class CityDoctorModelTest { @Test public void testCollectErrors() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Building b = new Building(); model.addBuilding(b); CheckError error = Mockito.mock(CheckError.class); @@ -247,18 +247,12 @@ public class CityDoctorModelTest { @Test public void testGetFileName() { - File f = new File("test"); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); assertEquals("test", model.getFileName()); - assertEquals(f, model.getFile()); + assertEquals(mockFile, model.getFile()); } @Test public void testSetCityModel() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); CityModel cModel = Mockito.mock(CityModel.class); model.setCityModel(cModel); assertEquals(cModel, model.getCityModel()); @@ -266,111 +260,99 @@ public class CityDoctorModelTest { @Test public void testAddBuilding() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Building b = Mockito.mock(Building.class); + Mockito.when(b.getGmlId()).thenReturn(new GmlId("b")); model.addBuilding(b); - assertEquals(b, model.getBuildings().get(0)); + assertEquals(b, model.getBuildings().toList().get(0)); } @Test public void testAddBridge() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); BridgeObject b = Mockito.mock(BridgeObject.class); + Mockito.when(b.getGmlId()).thenReturn(new GmlId("b")); model.addBridge(b); - assertEquals(b, model.getBridges().get(0)); + assertEquals(b, model.getBridges().toList().get(0)); } @Test public void testAddVegetation() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Vegetation veg = Mockito.mock(Vegetation.class); + Mockito.when(veg.getGmlId()).thenReturn(new GmlId("v")); model.addVegetation(veg); - assertEquals(veg, model.getVegetation().get(0)); + assertEquals(veg, model.getVegetation().toList().get(0)); } @Test public void testAddTunnel() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Tunnel tunnel = Mockito.mock(Tunnel.class); + Mockito.when(tunnel.getGmlId()).thenReturn(new GmlId("t")); model.addTunnel(tunnel); - assertEquals(tunnel, model.getTunnels().get(0)); + assertEquals(tunnel, model.getTunnels().toList().get(0)); } @Test public void testAddTransportation() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); TransportationObject trans = Mockito.mock(TransportationObject.class); + Mockito.when(trans.getGmlId()).thenReturn(new GmlId("t")); model.addTransportation(trans); - assertEquals(trans, model.getTransportation().get(0)); + assertEquals(trans, model.getTransportation().toList().get(0)); } @Test public void testAddLand() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); LandObject land = Mockito.mock(LandObject.class); + Mockito.when(land.getGmlId()).thenReturn(new GmlId("l")); model.addLand(land); - assertEquals(land, model.getLand().get(0)); + assertEquals(land, model.getLand().toList().get(0)); } @Test public void testAddWater() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); WaterObject water = Mockito.mock(WaterObject.class); + Mockito.when(water.getGmlId()).thenReturn(new GmlId("w")); model.addWater(water); - assertEquals(water, model.getWater().get(0)); + assertEquals(water, model.getWater().toList().get(0)); } @Test public void testAddCityFurniture() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); CityFurniture cf = Mockito.mock(CityFurniture.class); + Mockito.when(cf.getGmlId()).thenReturn(new GmlId("cf")); model.addCityFurniture(cf); - assertEquals(cf, model.getCityFurniture().get(0)); + assertEquals(cf, model.getCityFurniture().toList().get(0)); } @Test - public void testAddGenericCityObject() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); + public void testAddOtherCityObject() { GenericCityObject gen = Mockito.mock(GenericCityObject.class); - model.addGenericCityObject(gen); - assertEquals(gen, model.getGenericCityObjects().get(0)); + Mockito.when(gen.getGmlId()).thenReturn(new GmlId("g")); + model.addOtherCityObject(gen); + assertEquals(gen, model.getOtherCityObjects().toList().get(0)); } @Test public void testGetNumberOfFeatures() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Building b = Mockito.mock(Building.class); + Mockito.when(b.getGmlId()).thenReturn(new GmlId("b")); BridgeObject bo = Mockito.mock(BridgeObject.class); + Mockito.when(bo.getGmlId()).thenReturn(new GmlId("bo")); Vegetation veg = Mockito.mock(Vegetation.class); + Mockito.when(veg.getGmlId()).thenReturn(new GmlId("ve")); Tunnel tunnel = Mockito.mock(Tunnel.class); + Mockito.when(tunnel.getGmlId()).thenReturn(new GmlId("t")); TransportationObject trans = Mockito.mock(TransportationObject.class); + Mockito.when(trans.getGmlId()).thenReturn(new GmlId("tr")); LandObject land = Mockito.mock(LandObject.class); + Mockito.when(land.getGmlId()).thenReturn(new GmlId("l")); WaterObject water = Mockito.mock(WaterObject.class); + Mockito.when(water.getGmlId()).thenReturn(new GmlId("w")); CityFurniture cf = Mockito.mock(CityFurniture.class); + Mockito.when(cf.getGmlId()).thenReturn(new GmlId("cf")); GenericCityObject generic = Mockito.mock(GenericCityObject.class); + Mockito.when(generic.getGmlId()).thenReturn(new GmlId("g")); model.addBuilding(b); model.addBridge(bo); @@ -380,7 +362,7 @@ public class CityDoctorModelTest { model.addLand(land); model.addWater(water); model.addCityFurniture(cf); - model.addGenericCityObject(generic); + model.addOtherCityObject(generic); assertEquals(9, model.getNumberOfFeatures()); @@ -388,31 +370,25 @@ public class CityDoctorModelTest { @Test public void testGetParserConfig() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); assertEquals(config, model.getParserConfig()); } @Test public void testReplaceBuilding() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Building b1 = Mockito.mock(Building.class); + Mockito.when(b1.getGmlId()).thenReturn(new GmlId("b1")); Building b2 = Mockito.mock(Building.class); + Mockito.when(b2.getGmlId()).thenReturn(new GmlId("b2")); + model.addBuilding(b1); - assertEquals(b1, model.getBuildings().get(0)); + assertEquals(b1, model.getBuildings().toList().get(0)); model.replaceFeature(b1, b2); - assertEquals(b2, model.getBuildings().get(0)); - assertEquals(1, model.getBuildings().size()); + assertEquals(b2, model.getBuildings().toList().get(0)); + assertEquals(1, model.getBuildings().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceBuildingMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Building b1 = Mockito.mock(Building.class); Building b2 = Mockito.mock(Building.class); model.replaceFeature(b1, b2); @@ -420,23 +396,19 @@ public class CityDoctorModelTest { @Test public void testReplaceBridge() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); BridgeObject b1 = Mockito.mock(BridgeObject.class); + Mockito.when(b1.getGmlId()).thenReturn(new GmlId("b1")); BridgeObject b2 = Mockito.mock(BridgeObject.class); + Mockito.when(b2.getGmlId()).thenReturn(new GmlId("b2")); model.addBridge(b1); - assertEquals(b1, model.getBridges().get(0)); + assertEquals(b1, model.getBridges().toList().get(0)); model.replaceFeature(b1, b2); - assertEquals(b2, model.getBridges().get(0)); - assertEquals(1, model.getBridges().size()); + assertEquals(b2, model.getBridges().toList().get(0)); + assertEquals(1, model.getBridges().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceBridgeMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); BridgeObject b1 = Mockito.mock(BridgeObject.class); BridgeObject b2 = Mockito.mock(BridgeObject.class); model.replaceFeature(b1, b2); @@ -444,23 +416,20 @@ public class CityDoctorModelTest { @Test public void testReplaceVegetation() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Vegetation v1 = Mockito.mock(Vegetation.class); + Mockito.when(v1.getGmlId()).thenReturn(new GmlId("v1")); Vegetation v2 = Mockito.mock(Vegetation.class); + Mockito.when(v2.getGmlId()).thenReturn(new GmlId("v2")); + model.addVegetation(v1); - assertEquals(v1, model.getVegetation().get(0)); + assertEquals(v1, model.getVegetation().toList().get(0)); model.replaceFeature(v1, v2); - assertEquals(v2, model.getVegetation().get(0)); - assertEquals(1, model.getVegetation().size()); + assertEquals(v2, model.getVegetation().toList().get(0)); + assertEquals(1, model.getVegetation().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceVegetationMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Vegetation v1 = Mockito.mock(Vegetation.class); Vegetation v2 = Mockito.mock(Vegetation.class); model.replaceFeature(v1, v2); @@ -468,23 +437,20 @@ public class CityDoctorModelTest { @Test public void testReplaceTunnel() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Tunnel t1 = Mockito.mock(Tunnel.class); + Mockito.when(t1.getGmlId()).thenReturn(new GmlId("t1")); Tunnel t2 = Mockito.mock(Tunnel.class); + Mockito.when(t2.getGmlId()).thenReturn(new GmlId("t2")); + model.addTunnel(t1); - assertEquals(t1, model.getTunnels().get(0)); + assertEquals(t1, model.getTunnels().toList().get(0)); model.replaceFeature(t1, t2); - assertEquals(t2, model.getTunnels().get(0)); - assertEquals(1, model.getTunnels().size()); + assertEquals(t2, model.getTunnels().toList().get(0)); + assertEquals(1, model.getTunnels().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceTunnelMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); Tunnel t1 = Mockito.mock(Tunnel.class); Tunnel t2 = Mockito.mock(Tunnel.class); model.replaceFeature(t1, t2); @@ -492,23 +458,20 @@ public class CityDoctorModelTest { @Test public void testReplaceTransportation() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); TransportationObject t1 = Mockito.mock(TransportationObject.class); + Mockito.when(t1.getGmlId()).thenReturn(new GmlId("t1")); TransportationObject t2 = Mockito.mock(TransportationObject.class); + Mockito.when(t2.getGmlId()).thenReturn(new GmlId("t2")); + model.addTransportation(t1); - assertEquals(t1, model.getTransportation().get(0)); + assertEquals(t1, model.getTransportation().toList().get(0)); model.replaceFeature(t1, t2); - assertEquals(t2, model.getTransportation().get(0)); - assertEquals(1, model.getTransportation().size()); + assertEquals(t2, model.getTransportation().toList().get(0)); + assertEquals(1, model.getTransportation().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceTransportationMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); TransportationObject t1 = Mockito.mock(TransportationObject.class); TransportationObject t2 = Mockito.mock(TransportationObject.class); model.replaceFeature(t1, t2); @@ -516,23 +479,20 @@ public class CityDoctorModelTest { @Test public void testReplaceLand() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); LandObject lo1 = Mockito.mock(LandObject.class); + Mockito.when(lo1.getGmlId()).thenReturn(new GmlId("lo1")); LandObject lo2 = Mockito.mock(LandObject.class); + Mockito.when(lo2.getGmlId()).thenReturn(new GmlId("lo2")); + model.addLand(lo1); - assertEquals(lo1, model.getLand().get(0)); + assertEquals(lo1, model.getLand().toList().get(0)); model.replaceFeature(lo1, lo2); - assertEquals(lo2, model.getLand().get(0)); - assertEquals(1, model.getLand().size()); + assertEquals(lo2, model.getLand().toList().get(0)); + assertEquals(1, model.getLand().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceLandMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); LandObject lo1 = Mockito.mock(LandObject.class); LandObject lo2 = Mockito.mock(LandObject.class); model.replaceFeature(lo1, lo2); @@ -540,23 +500,20 @@ public class CityDoctorModelTest { @Test public void testReplaceWater() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); WaterObject t1 = Mockito.mock(WaterObject.class); + Mockito.when(t1.getGmlId()).thenReturn(new GmlId("t1")); WaterObject t2 = Mockito.mock(WaterObject.class); + Mockito.when(t2.getGmlId()).thenReturn(new GmlId("t2")); + model.addWater(t1); - assertEquals(t1, model.getWater().get(0)); + assertEquals(t1, model.getWater().toList().get(0)); model.replaceFeature(t1, t2); - assertEquals(t2, model.getWater().get(0)); - assertEquals(1, model.getWater().size()); + assertEquals(t2, model.getWater().toList().get(0)); + assertEquals(1, model.getWater().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceWaterMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); WaterObject t1 = Mockito.mock(WaterObject.class); WaterObject t2 = Mockito.mock(WaterObject.class); model.replaceFeature(t1, t2); @@ -564,23 +521,20 @@ public class CityDoctorModelTest { @Test public void testReplaceCityFurniture() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); CityFurniture cf1 = Mockito.mock(CityFurniture.class); + Mockito.when(cf1.getGmlId()).thenReturn(new GmlId("cf1")); CityFurniture cf2 = Mockito.mock(CityFurniture.class); + Mockito.when(cf2.getGmlId()).thenReturn(new GmlId("cf2")); + model.addCityFurniture(cf1); - assertEquals(cf1, model.getCityFurniture().get(0)); + assertEquals(cf1, model.getCityFurniture().toList().get(0)); model.replaceFeature(cf1, cf2); - assertEquals(cf2, model.getCityFurniture().get(0)); - assertEquals(1, model.getCityFurniture().size()); + assertEquals(cf2, model.getCityFurniture().toList().get(0)); + assertEquals(1, model.getCityFurniture().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceCityFurnitureMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); CityFurniture cf1 = Mockito.mock(CityFurniture.class); CityFurniture cf2 = Mockito.mock(CityFurniture.class); model.replaceFeature(cf1, cf2); @@ -588,23 +542,20 @@ public class CityDoctorModelTest { @Test public void testReplaceGenericCityObject() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); GenericCityObject gco1 = Mockito.mock(GenericCityObject.class); + Mockito.when(gco1.getGmlId()).thenReturn(new GmlId("gco1")); GenericCityObject gco2 = Mockito.mock(GenericCityObject.class); - model.addGenericCityObject(gco1); - assertEquals(gco1, model.getGenericCityObjects().get(0)); + Mockito.when(gco2.getGmlId()).thenReturn(new GmlId("gco2")); + + model.addOtherCityObject(gco1); + assertEquals(gco1, model.getOtherCityObjects().toList().get(0)); model.replaceFeature(gco1, gco2); - assertEquals(gco2, model.getGenericCityObjects().get(0)); - assertEquals(1, model.getGenericCityObjects().size()); + assertEquals(gco2, model.getOtherCityObjects().toList().get(0)); + assertEquals(1, model.getOtherCityObjects().toList().size()); } @Test(expected = IllegalStateException.class) public void testReplaceGenericCityObjectMissing() { - File f = Mockito.mock(File.class); - ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, f); GenericCityObject gco1 = Mockito.mock(GenericCityObject.class); GenericCityObject gco2 = Mockito.mock(GenericCityObject.class); model.replaceFeature(gco1, gco2); diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygonTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygonTest.java index 7aa9ad7763c3c949010b4464d2567ffc94d12042..9c306ab34964f5cba514843072d70110439109d3 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygonTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/CompositePolygonTest.java @@ -16,7 +16,7 @@ public class CompositePolygonTest { ParserConfiguration config = new ParserConfiguration(8, false); CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/FZK_haus.gml", config); - Building b = m.getBuildings().get(0); + Building b = m.getBuildings().toList().get(0); assertNotNull(b); assertFalse(b.getBoundarySurfaces().isEmpty()); for (BoundarySurface bs : b.getBoundarySurfaces()) { diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/GeometryTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/GeometryTest.java index a37077ae28fbca4d79961e9bb2a5141afabdbe79..5c8b97cff5c28a6c4b8b9e1308253988999b70f3 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/GeometryTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/GeometryTest.java @@ -96,7 +96,7 @@ public class GeometryTest { public void testRemovePolygonConcreteWithLink() { ParserConfiguration config = new ParserConfiguration(4, false); AbstractConstructionSurface abs = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, abs); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, abs); var gmlBi = new org.citygml4j.core.model.building.BuildingInstallation(); Installation bi = new Installation(); bi.setGmlObject(gmlBi); @@ -133,7 +133,7 @@ public class GeometryTest { public void testRemovePolygonOnlyConcrete() { ParserConfiguration config = new ParserConfiguration(4, false); AbstractConstructionSurface abs = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, abs); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, abs); Geometry geom = new Geometry(GeometryType.MULTI_SURFACE, Lod.LOD2, Orientation.OUTWARD); ConcretePolygon p = new ConcretePolygon(); @@ -156,7 +156,7 @@ public class GeometryTest { public void testRemovePolygonLinked() { ParserConfiguration config = new ParserConfiguration(4, false); AbstractConstructionSurface abs = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, abs); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, abs); var gmlBi = new org.citygml4j.core.model.building.BuildingInstallation(); Installation bi = new Installation(); bi.setGmlObject(gmlBi); @@ -193,7 +193,7 @@ public class GeometryTest { public void testReplacePolygon() { ParserConfiguration config = new ParserConfiguration(4, false); AbstractConstructionSurface abs = new WallSurface(); - BoundarySurface bs = new BoundarySurface(SurfaceFeatureType.BUILDING, BoundarySurfaceType.WALL, abs); + BoundarySurface bs = new BoundarySurface(BoundarySurfaceType.WALL, abs); var gmlBi = new org.citygml4j.core.model.building.BuildingInstallation(); Installation bi = new Installation(); bi.setGmlObject(gmlBi); diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/VegetationTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/VegetationTest.java index 5f9c97a3f29f5bb6dd70e7ed4cdb3df3c51dd964..4df104691c64bb4c5f1535ea058b9ac285172a50 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/VegetationTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/VegetationTest.java @@ -26,7 +26,6 @@ import static org.mockito.Mockito.mock; public class VegetationTest { - //TODO: Recreate geometries tests @Test public void testContainsError() { diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/mapper/FeatureMapperTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/mapper/FeatureMapperTest.java index a4d8f261a8a6f70f685dbb5d9b64592ca5708849..456d40124bc646f364c306016fc84c5a80177a68 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/mapper/FeatureMapperTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/mapper/FeatureMapperTest.java @@ -63,20 +63,20 @@ public class FeatureMapperTest { public void testVisitWaterBody() { WaterBody body = new WaterBody(); Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(mock(ParserConfiguration.class), - new File("").toPath()); + new File("").toPath(), false); mapper.visit(body); - assertEquals(1, mapper.getModel().getWater().size()); + assertEquals(1, mapper.getModel().getWater().toList().size()); body.setId("test1"); mapper.visit(body); - assertEquals(2, mapper.getModel().getWater().size()); - WaterObject waterObject = mapper.getModel().getWater().get(1); + assertEquals(2, mapper.getModel().getWater().toList().size()); + WaterObject waterObject = mapper.getModel().getWater().toList().get(1); assertEquals("test1", waterObject.getGmlId().getGmlString()); body.getDeprecatedProperties().setLod1MultiSurface(createDummyMsp()); mapper.visit(body); - assertEquals(3, mapper.getModel().getWater().size()); + assertEquals(3, mapper.getModel().getWater().toList().size()); assertNull(body.getDeprecatedProperties().getLod1MultiSurface()); - Geometry geometry = mapper.getModel().getWater().get(2).getGeometries().get(0); + Geometry geometry = mapper.getModel().getWater().toList().get(2).getGeometries().get(0); assertEquals(1, geometry.getPolygons().size()); assertEquals(Lod.LOD1, geometry.getLod()); assertEquals(GeometryType.MULTI_SURFACE, geometry.getType()); @@ -86,7 +86,7 @@ public class FeatureMapperTest { public void testVisitPlantCover() { PlantCover cover = new PlantCover(); Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(mock(ParserConfiguration.class), - new File("").toPath()); + new File("").toPath(), false); mapper.visit(cover); } @@ -124,12 +124,12 @@ public class FeatureMapperTest { body.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms)); ParserConfiguration config = new ParserConfiguration(8, false); - Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, folder.newFile().toPath()); + Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, folder.newFile().toPath(), false); mapper.visit(body); CityDoctorModel model = mapper.getModel(); - assertEquals(1, model.getWater().size()); - WaterObject waterObject = model.getWater().get(0); + assertEquals(1, model.getWater().toList().size()); + WaterObject waterObject = model.getWater().toList().get(0); Geometry geometry = waterObject.getGeometries().get(0); assertEquals(1, geometry.getVertices().size()); Vertex vertex = geometry.getVertices().get(0); @@ -152,12 +152,12 @@ public class FeatureMapperTest { body.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms)); ParserConfiguration config = new ParserConfiguration(8, false); - Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, folder.newFile().toPath()); + Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, folder.newFile().toPath(), false); mapper.visit(body); CityDoctorModel model = mapper.getModel(); - assertEquals(1, model.getWater().size()); - WaterObject waterObject = model.getWater().get(0); + assertEquals(1, model.getWater().toList().size()); + WaterObject waterObject = model.getWater().toList().get(0); Geometry geometry = waterObject.getGeometries().get(0); assertEquals(2, geometry.getVertices().size()); Vertex vertex = geometry.getVertices().get(0); @@ -199,12 +199,12 @@ public class FeatureMapperTest { body.getDeprecatedProperties().setLod1MultiSurface(new MultiSurfaceProperty(ms)); ParserConfiguration config = new ParserConfiguration(8, false); - Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, folder.newFile().toPath()); + Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, folder.newFile().toPath(), false); mapper.visit(body); CityDoctorModel model = mapper.getModel(); - assertEquals(1, model.getWater().size()); - WaterObject waterObject = model.getWater().get(0); + assertEquals(1, model.getWater().toList().size()); + WaterObject waterObject = model.getWater().toList().get(0); Geometry geometry = waterObject.getGeometries().get(0); assertEquals(7, geometry.getVertices().size()); assertEquals(8, geometry.getEdges().size()); diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/parser/CityGml3ParserTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/parser/CityGml3ParserTest.java index cbc926f156477550c15a2256c742e161ada87269..88b958f4f01ef0083bb0bb8ed262e8ca71b3e0bb 100644 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/parser/CityGml3ParserTest.java +++ b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/parser/CityGml3ParserTest.java @@ -49,7 +49,7 @@ public class CityGml3ParserTest { ParserConfiguration config = new ParserConfiguration(8, false); CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/SimpleSolid_SrefBS.gml", config); assertNotNull(model); - List buildings = model.getBuildings(); + List buildings = model.getBuildings().toList(); assertEquals(1, buildings.size()); Building building = buildings.get(0); assertEquals("_Simple_BD.1", building.getGmlId().getGmlString()); diff --git a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java b/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java deleted file mode 100644 index cb9b8e2b612c3f80c136da4df1962f487ba14d8c..0000000000000000000000000000000000000000 --- a/CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/zip/ZipTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package de.hft.stuttgart.citydoctor2.zip; - -import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; -import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; -import org.apache.commons.io.FileUtils; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class ZipTest { - - ParserConfiguration config = new ParserConfiguration(8, false); - - - @Test - public void testUnzipping() throws MalformedZipFileException { - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/mock_archive.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(config); - - checkMockArchive(cgmlArch); - } - - private void checkMockArchive(CityGmlZipArchive cgmlArch) { - assertEquals(5, cgmlArch.getEntries().size()); - for (CityGmlZipEntry entry : cgmlArch.getEntries()) { - assertNotNull(entry); - assertTrue(entry.getEntrySubPath().matches("^mock[1-5].gml$")); - assertNull(entry.getErrorType()); - assertNotNull(entry.getModel()); - assertEquals(1, entry.getModel().getNumberOfFeatures()); - } - } - - @Test - public void testZipping() throws IOException { - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/mock_archive.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(config); - - Path tmpDir = null; - try { - tmpDir = Files.createTempDirectory("testTmp"); - tmpDir.toFile().deleteOnExit(); - String expPath = tmpDir + "/export.zip"; - - cgmlArch.exportToZipFile(expPath); - CityGmlZipArchive cgmlExport = CityGmlZipArchive.register(expPath); - assertNotNull(cgmlExport); - cgmlExport.mountArchive(config); - - checkMockArchive(cgmlExport); - } finally { - if (tmpDir != null) { - FileUtils.deleteDirectory(tmpDir.toFile()); - } - } - } - - @Test - public void testEpsgParsing() throws MalformedZipFileException { - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/epsg.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(config); - - CityGmlZipEntry entry = cgmlArch.getEntry("epsg1.gml"); - assertNotNull(entry); - String srsName = entry.getModel().getCityModel().getBoundedBy().getEnvelope().getSrsName().split(":")[6]; - assertEquals("25832", srsName); - - entry = cgmlArch.getEntry("epsg2.gml"); - assertNotNull(entry); - srsName = entry.getModel().getCityModel().getBoundedBy().getEnvelope().getSrsName().split(":")[6]; - assertEquals("7415", srsName); - } - - @Test - public void testXMLValidation() throws MalformedZipFileException { - ParserConfiguration valConfig = new ParserConfiguration(8, true); - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/validate.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(valConfig); - - assertNull(cgmlArch.getEntry("valCorrect.gml").getErrorType()); - assertEquals(ZipEntryErrorType.INVALID_CITY_GML_FILE, cgmlArch.getEntry("valFaulty.gml").getErrorType()); - } - - - @Test - public void testImplicitParsing() throws MalformedZipFileException { - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zip/implicit.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(config); - - CityDoctorModel mainModel = cgmlArch.getEntry("Main_model.gml").getModel(); - assertEquals(18, mainModel.getGenericCityObjects().size()); - } - -} diff --git a/CityDoctorParent/CityDoctorModel/src/test/resources/04-FZK-Haus-LoD2-Tex-Storey-CG30-V01-InteriorSurface.gml b/CityDoctorParent/CityDoctorModel/src/test/resources/04-FZK-Haus-LoD2-Tex-Storey-CG30-V01-InteriorSurface.gml new file mode 100644 index 0000000000000000000000000000000000000000..da8303f785cdf9dbd703cde6d8717e64c3fafa2b --- /dev/null +++ b/CityDoctorParent/CityDoctorModel/src/test/resources/04-FZK-Haus-LoD2-Tex-Storey-CG30-V01-InteriorSurface.gml @@ -0,0 +1,1655 @@ + + + + + + + + + FZK-Haus + + + 458900.0 5438785.0 113.5 + 458912.0 5438795.0 120.017691 + + + + + KIT Test Building FZK-Haus adapted for CityGML 3.0 + KIT Test Building FZK-Haus for CityGML 3.0 + + + @cityeditor:layer + LoD2-Ausgeblendet + + + + + + + + + + + + + + + + + + + + + + projected + + + highestRoofEdge + lowestGroundPoint + measured + 6.52 + + + + + 2 + + + + + Ground Floor + + + Ground + + + + + + + 458912.0 5438785.0 + 113.5 458900.0 5438785.0 113.5 458900.0 5438795.0 + 113.5 458912.0 5438795.0 113.5 458912.0 5438785.0 + 113.5 + + + + + + + + + + + Ground Floor / Wall East + + + + + + + 458912.0 5438795.0 + 113.5 458912.0 5438795.0 116.4 458912.0 5438785.0 + 116.4 458912.0 5438785.0 113.5 458912.0 5438795.0 + 113.5 + + + + + + + + + + + Ground Floor / Wall South + + + + + + + 458912.0 5438785.0 + 113.5 458912.0 5438785.0 116.4 458900.0 5438785.0 + 116.4 458900.0 5438785.0 113.5 458912.0 5438785.0 + 113.5 + + + + + + + + + + + Ground Floor / Wall West + + + + + + + 458900.0 5438785.0 + 113.5 458900.0 5438785.0 116.4 458900.0 5438795.0 + 116.4 458900.0 5438795.0 113.5 458900.0 5438785.0 + 113.5 + + + + + + + + + + + Ground Floor / Wall North + + + + + + + 458900.0 5438795.0 + 113.5 458900.0 5438795.0 116.4 458912.0 5438795.0 + 116.4 458912.0 5438795.0 113.5 458900.0 5438795.0 + 113.5 + + + + + + + + + + + 02 Ground Floor - Kitchen + + + Ground Floor / Kitchen / Closure Surface North + + + + + + + 458904.695 + 5438789.01 116.2 458903.8 5438789.01 116.2 + 458903.8 5438789.01 113.7 458904.695 5438789.01 + 113.7 458904.695 5438789.01 116.2 + + + + + + + + + + + Ground Floor / Kitchen / Closure Surface East + + + + + + + 458904.695 + 5438789.01 116.2 458904.695 5438789.01 113.7 + 458904.695 5438785.3 113.7 458904.695 5438785.3 + 116.2 458904.695 5438789.01 116.2 + + + + + + + + + + + Ground Floor / Kitchen / Ceiling + + + + + + + 458900.3 5438785.3 + 116.2 458900.3 5438789.01 116.2 458903.8 + 5438789.01 116.2 458904.695 5438789.01 116.2 + 458904.695 5438785.3 116.2 458900.3 5438785.3 + 116.2 + + + + + + + + + + + Ground Floor / Kitchen / Interior Wall West + + + + + + + 458900.3 5438785.3 + 116.2 458900.3 5438785.3 113.7 458900.3 5438789.01 + 113.7 458900.3 5438789.01 116.2 458900.3 5438785.3 + 116.2 + + + + + + + + + + + Ground Floor / Kitchen / Interior Wall South + + + + + + + 458904.695 5438785.3 + 116.2 458904.695 5438785.3 113.7 458900.3 + 5438785.3 113.7 458900.3 5438785.3 116.2 + 458904.695 5438785.3 116.2 + + + + + + + + + + + Ground Floor / Kitchen / Interior Wall North + + + + + + + 458900.3 5438789.01 + 113.7 458903.8 5438789.01 113.7 458903.8 + 5438789.01 116.2 458900.3 5438789.01 116.2 + 458900.3 5438789.01 113.7 + + + + + + + + + + + Ground Floor / Kitchen / Floor + + + + + + + 458903.8 5438789.01 + 113.7 458900.3 5438789.01 113.7 458900.3 5438785.3 + 113.7 458904.695 5438785.3 113.7 458904.695 + 5438789.01 113.7 458903.8 5438789.01 + 113.7 + + + + + + + + + + + + + 03 Ground Floor - Corridor + + + Ground Floor / Corridor / Closure Surface South + + + + + + + 458907.41 5438789.01 + 113.7 458904.695 5438789.01 113.7 458904.695 + 5438789.01 116.2 458907.41 5438789.01 116.2 + 458907.41 5438789.01 113.7 + + + + + + + + + + + Ground Floor / Corridor / Closure Surface South + + + + + + + 458903.8 5438789.01 + 116.2 458904.695 5438789.01 116.2 458904.695 + 5438789.01 113.7 458903.8 5438789.01 113.7 + 458903.8 5438789.01 116.2 + + + + + + + + + + + Ground Floor / Corridor / Ceiling + + + + + + + 458903.8 5438789.25 + 116.2 458900.3 5438789.25 116.2 458900.3 + 5438790.75 116.2 458907.41 5438790.75 116.2 + 458907.41 5438789.01 116.2 458904.695 5438789.01 + 116.2 458903.8 5438789.01 116.2 458903.8 + 5438789.25 116.2 + + + + + + + + + + + Ground Floor / Corridor / Wall East + + + + + + + 458907.41 5438790.75 + 116.2 458907.41 5438790.75 113.7 458907.41 + 5438789.01 113.7 458907.41 5438789.01 116.2 + 458907.41 5438790.75 116.2 + + + + + + + + + + + Ground Floor / Corridor / Wall North + + + + + + + 458900.3 5438790.75 + 113.7 458907.41 5438790.75 113.7 458907.41 + 5438790.75 116.2 458900.3 5438790.75 116.2 + 458900.3 5438790.75 113.7 + + + + + + + + + + + Ground Floor / Corridor / Wall West I + + + + + + + 458900.3 5438789.25 + 113.7 458900.3 5438790.75 113.7 458900.3 + 5438790.75 116.2 458900.3 5438789.25 116.2 + 458900.3 5438789.25 113.7 + + + + + + + + + + + Ground Floor / Corridor / Wall South + + + + + + + 458903.8 5438789.25 + 113.7 458900.3 5438789.25 113.7 458900.3 + 5438789.25 116.2 458903.8 5438789.25 116.2 + 458903.8 5438789.25 113.7 + + + + + + + + + + + Ground Floor / Corridor / Wall West II + + + + + + + 458903.8 5438789.01 + 113.7 458903.8 5438789.25 113.7 458903.8 + 5438789.25 116.2 458903.8 5438789.01 116.2 + 458903.8 5438789.01 113.7 + + + + + + + + + + + Ground Floor / Corridor / Floor + + + + + + + 458903.8 5438789.01 + 113.7 458904.695 5438789.01 113.7 458907.41 + 5438789.01 113.7 458907.41 5438790.75 113.7 + 458900.3 5438790.75 113.7 458900.3 5438789.25 + 113.7 458903.8 5438789.25 113.7 458903.8 + 5438789.01 113.7 + + + + + + + + + + + + + 04 Ground Floor - Living Room + + + Ground Floor / Living Room / Closure Surface West + + + + + + + 458904.695 5438785.3 + 116.2 458904.695 5438785.3 113.7 458904.695 + 5438789.01 113.7 458904.695 5438789.01 116.2 + 458904.695 5438785.3 116.2 + + + + + + + + + + + Ground Floor / Living Room / Closure Surface North + + + + + + + 458904.695 + 5438789.01 113.7 458907.41 5438789.01 113.7 + 458907.41 5438789.01 116.2 458904.695 5438789.01 + 116.2 458904.695 5438789.01 113.7 + + + + + + + + + + + Ground Floor / Living Room / Ceiling + + + + + + + 458904.695 + 5438789.01 116.2 458907.41 5438789.01 116.2 + 458911.7 5438789.01 116.2 458911.7 5438785.3 116.2 + 458904.695 5438785.3 116.2 458904.695 5438789.01 + 116.2 + + + + + + + + + + + Ground Floor / Living Room / Interior Wall North + + + + + + + 458911.7 5438789.01 + 116.2 458907.41 5438789.01 116.2 458907.41 + 5438789.01 113.7 458911.7 5438789.01 113.7 + 458911.7 5438789.01 116.2 + + + + + + + + + + + Ground Floor / Living Room / Interior Wall South + + + + + + + 458911.7 5438785.3 + 116.2 458911.7 5438785.3 113.7 458904.695 + 5438785.3 113.7 458904.695 5438785.3 116.2 + 458911.7 5438785.3 116.2 + + + + + + + + + + + Ground Floor / Living Room / Interior Wall East + + + + + + + 458911.7 5438789.01 + 116.2 458911.7 5438789.01 113.7 458911.7 5438785.3 + 113.7 458911.7 5438785.3 116.2 458911.7 5438789.01 + 116.2 + + + + + + + + + + + Ground Floor / Living Room / Floor + + + + + + + 458904.695 5438785.3 + 113.7 458911.7 5438785.3 113.7 458911.7 5438789.01 + 113.7 458907.41 5438789.01 113.7 458904.695 + 5438789.01 113.7 458904.695 5438785.3 + 113.7 + + + + + + + + + + + + + 05 Ground Floor - Bedroom + + + Ground Floor / Bedroom / Ceiling + + + + + + + 458911.7 5438789.25 + 116.2 458907.65 5438789.25 116.2 458907.65 + 5438794.7 116.2 458911.7 5438794.7 116.2 458911.7 + 5438789.25 116.2 + + + + + + + + + + + Ground Floor / Bedroom / Interior Wall West + + + + + + + 458907.65 5438789.25 + 116.2 458907.65 5438789.25 113.7 458907.65 + 5438794.7 113.7 458907.65 5438794.7 116.2 + 458907.65 5438789.25 116.2 + + + + + + + + + + + Ground Floor / Bedroom / Interior Wall South + + + + + + + 458911.7 5438789.25 + 116.2 458911.7 5438789.25 113.7 458907.65 + 5438789.25 113.7 458907.65 5438789.25 116.2 + 458911.7 5438789.25 116.2 + + + + + + + + + + + Ground Floor / Bedroom / Interior Wall North + + + + + + + 458907.65 5438794.7 + 116.2 458907.65 5438794.7 113.7 458911.7 5438794.7 + 113.7 458911.7 5438794.7 116.2 458907.65 5438794.7 + 116.2 + + + + + + + + + + + Ground Floor / Bedroom / Interior Wall East + + + + + + + 458911.7 5438794.7 + 116.2 458911.7 5438794.7 113.7 458911.7 5438789.25 + 113.7 458911.7 5438789.25 116.2 458911.7 5438794.7 + 116.2 + + + + + + + + + + + Ground Floor / Bedroom / Floor + + + + + + + 458911.7 5438789.25 + 113.7 458911.7 5438794.7 113.7 458907.65 5438794.7 + 113.7 458907.65 5438789.25 113.7 458911.7 + 5438789.25 113.7 + + + + + + + + + + + + + 06 Ground Floor - Bathroom + + + Ground Floor / Bathroom / Ceiling + + + + + + + 458907.41 5438790.99 + 116.2 458904.04 5438790.99 116.2 458904.04 + 5438794.7 116.2 458907.41 5438794.7 116.2 + 458907.41 5438790.99 116.2 + + + + + + + + + + + Ground Floor / Bathroom / Interior Wall West + + + + + + + 458904.04 5438790.99 + 116.2 458904.04 5438790.99 113.7 458904.04 + 5438794.7 113.7 458904.04 5438794.7 116.2 + 458904.04 5438790.99 116.2 + + + + + + + + + + + Ground Floor / Bathroom / Interior Wall South + + + + + + + 458907.41 5438790.99 + 116.2 458907.41 5438790.99 113.7 458904.04 + 5438790.99 113.7 458904.04 5438790.99 116.2 + 458907.41 5438790.99 116.2 + + + + + + + + + + + Ground Floor / Bathroom / Interior Wall North + + + + + + + 458904.04 5438794.7 + 116.2 458904.04 5438794.7 113.7 458907.41 + 5438794.7 113.7 458907.41 5438794.7 116.2 + 458904.04 5438794.7 116.2 + + + + + + + + + + + Ground Floor / Bathroom / Interior Wall East + + + + + + + 458907.41 5438794.7 + 116.2 458907.41 5438794.7 113.7 458907.41 + 5438790.99 113.7 458907.41 5438790.99 116.2 + 458907.41 5438794.7 116.2 + + + + + + + + + + + Ground Floor / Bathroom / Floor + + + + + + + 458907.41 5438790.99 + 113.7 458907.41 5438794.7 113.7 458904.04 + 5438794.7 113.7 458904.04 5438790.99 113.7 + 458907.41 5438790.99 113.7 + + + + + + + + + + + + + 07 Ground Floor - Office + + + Ground Floor / Office / Ceiling + + + + + + + 458903.8 5438790.99 + 116.2 458900.3 5438790.99 116.2 458900.3 5438794.7 + 116.2 458903.8 5438794.7 116.2 458903.8 5438790.99 + 116.2 + + + + + + + + + + + Ground Floor / Office / Interior Wall West + + + + + + + 458900.3 5438790.99 + 116.2 458900.3 5438790.99 113.7 458900.3 5438794.7 + 113.7 458900.3 5438794.7 116.2 458900.3 5438790.99 + 116.2 + + + + + + + + + + + Ground Floor / Office / Interior Wall South + + + + + + + 458903.8 5438790.99 + 116.2 458903.8 5438790.99 113.7 458900.3 + 5438790.99 113.7 458900.3 5438790.99 116.2 + 458903.8 5438790.99 116.2 + + + + + + + + + + + Ground Floor / Office / Interior Wall North + + + + + + + 458900.3 5438794.7 + 116.2 458900.3 5438794.7 113.7 458903.8 5438794.7 + 113.7 458903.8 5438794.7 116.2 458900.3 5438794.7 + 116.2 + + + + + + + + + + + Ground Floor / Office / Interior Wall East + + + + + + + 458903.8 5438794.7 + 116.2 458903.8 5438794.7 113.7 458903.8 5438790.99 + 113.7 458903.8 5438790.99 116.2 458903.8 5438794.7 + 116.2 + + + + + + + + + + + Ground Floor / Office / Floor + + + + + + + 458903.8 5438790.99 + 113.7 458903.8 5438794.7 113.7 458900.3 5438794.7 + 113.7 458900.3 5438790.99 113.7 458903.8 + 5438790.99 113.7 + + + + + + + + + + + + + + + Second Floor + + + Second Floor / Roof South + + + + + + + 458912.0 5438790.0 + 120.017691 458900.0 5438790.0 120.017691 458900.0 + 5438785.0 117.13094 458912.0 5438785.0 117.13094 + 458912.0 5438790.0 120.017691 + + + + + + + + + + + Second Floor / Roof North + + + + + + + 458900.0 5438790.0 + 120.017691 458912.0 5438790.0 120.017691 458912.0 + 5438795.0 117.13094 458900.0 5438795.0 117.13094 + 458900.0 5438790.0 120.017691 + + + + + + + + + + + Second Floor / Wall South + + + + + + + 458900.0 5438785.0 + 117.13094 458900.0 5438785.0 116.4 458912.0 + 5438785.0 116.4 458912.0 5438785.0 117.13094 + 458900.0 5438785.0 117.13094 + + + + + + + + + + + Second Floor / Wall West + + + + + + + 458900.0 5438795.0 + 117.13094 458900.0 5438795.0 116.4 458900.0 + 5438785.0 116.4 458900.0 5438785.0 117.13094 + 458900.0 5438790.0 120.017691 458900.0 5438795.0 + 117.13094 + + + + + + + + + + + Second Floor / Wall East + + + + + + + 458912.0 5438785.0 + 117.13094 458912.0 5438785.0 116.4 458912.0 + 5438795.0 116.4 458912.0 5438795.0 117.13094 + 458912.0 5438790.0 120.017691 458912.0 5438785.0 + 117.13094 + + + + + + + + + + + Second Floor / Wall North + + + + + + + 458912.0 5438795.0 + 117.13094 458912.0 5438795.0 116.4 458900.0 + 5438795.0 116.4 458900.0 5438795.0 117.13094 + 458912.0 5438795.0 117.13094 + + + + + + + + + + + 01 Second Floor - Galery + + + Second Floor / Galery / Ceiling North + + + + + + + 458900.3 5438794.7 + 117.073205 458911.7 5438794.7 117.073205 458911.7 + 5438790.0 119.786751 458900.3 5438790.0 119.786751 + 458900.3 5438794.7 117.073205 + + + + + + + + + + + Second Floor / Galery / Ceiling South + + + + + + + 458900.3 5438785.3 + 117.073205 458900.3 5438790.0 119.786751 458911.7 + 5438790.0 119.786751 458911.7 5438785.3 117.073205 + 458900.3 5438785.3 117.073205 + + + + + + + + + + + Second Floor / Galery / Interior Wall North + + + + + + + 458911.7 5438794.7 + 116.4 458911.7 5438794.7 117.073205 458900.3 + 5438794.7 117.073205 458900.3 5438794.7 116.4 + 458911.7 5438794.7 116.4 + + + + + + + + + + + Second Floor / Galery / Interior Wall East + + + + + + + 458911.7 5438794.7 + 117.073205 458911.7 5438794.7 116.4 458911.7 + 5438785.3 116.4 458911.7 5438785.3 117.073205 + 458911.7 5438790.0 119.786751 458911.7 5438794.7 + 117.073205 + + + + + + + + + + + Second Floor / Galery / Interior Wall West + + + + + + + 458900.3 5438790.0 + 119.786751 458900.3 5438785.3 117.073205 458900.3 + 5438785.3 116.4 458900.3 5438794.7 116.4 458900.3 + 5438794.7 117.073205 458900.3 5438790.0 + 119.786751 + + + + + + + + + + + Second Floor / Galery / Interior Wall South + + + + + + + 458900.3 5438785.3 + 116.4 458900.3 5438785.3 117.073205 458911.7 + 5438785.3 117.073205 458911.7 5438785.3 116.4 + 458900.3 5438785.3 116.4 + + + + + + + + + + + Second Floor / Galery / Floor + + + + + + + 458911.7 5438785.3 + 116.4 458911.7 5438794.7 116.4 458900.3 5438794.7 + 116.4 458900.3 5438785.3 116.4 458911.7 5438785.3 + 116.4 + + + + + + + + + + + + + + + + + + + textures/FZK-Haus-Front.png + wrap + + + #KIT-Test-Building-01_PG.nfWbzHM5j2MqtisYAjgV + + + -6.01592849610218e-17 1.000011046207786 + -3.0079642480510886e-17 0.7987000468203478 + 1.0000000000000002 0.7987000468203478 1.0000000000000002 + 1.000011046207786 -6.01592849610218e-17 + 1.000011046207786 + #KIT-Test-Building-01_LR.l5vPQsQlvAxe0PfGrItK + + + + + + + #KIT-Test-Building-01_PG.8Oi6zRMGuUdvjDA3942O + + + 1.0000000000000002 + -4.454490602082857e-31 1.0000000000000002 0.7987000468203478 + -3.007964248051091e-17 0.7987000468203478 0.0 + -5.359579389737923e-47 1.0000000000000002 + -4.454490602082857e-31 + #KIT-Test-Building-01_LR.dQRaAbGZocTDsiXUS3Wo + + + + + + + + + textures/FZK-Haus-Right.png + wrap + + + #KIT-Test-Building-01_PG.ioJ6HX4PnhWvLSYhPA7h + + + 7.560328766851198e-17 + 0.5570891737385654 5.087501393878691e-16 0.444942234223729 + 1.0000000000000004 0.44494223422372897 1.0000000000000004 + 0.5570891737385655 0.49999999999999994 0.9999986887435715 + 7.560328766851198e-17 0.5570891737385654 + #KIT-Test-Building-01_LR.VpCnRrYqLGD4bFFZLmWC + + + + + + + #KIT-Test-Building-01_PG.WH3ZPoThoidUosBGLd28 + + + 1.0000000000000004 + -2.907494171674344e-16 1.0000000000000004 + 0.44494223422372897 5.087501393878691e-16 0.444942234223729 + 7.560328766851198e-17 -2.907494171674344e-16 + 1.0000000000000004 + -2.907494171674344e-16 + #KIT-Test-Building-01_LR.kb6UBRDjXdQhuZgyrrXF + + + + + + + + + textures/FZK-Haus-Left.png + wrap + + + #KIT-Test-Building-01_PG.VdnPNlkOAJHnTVZL5R37 + + + -1.0 0.5570891737385658 + -0.9999999999999996 0.44494223422372936 + 4.331468517193571e-16 0.44494223422372936 + 4.331468517193571e-16 0.5570891737385657 + -0.49999999999999944 0.9999986887435719 -1.0 + 0.5570891737385658 + #KIT-Test-Building-01_LR.CWPcEAowucw9pxGFPH3S + + + + + + + #KIT-Test-Building-01_PG.87LG6xx5gYYjprCeHCDY + + + 4.331468517193571e-16 + -1.1157709843049066e-47 4.331468517193571e-16 + 0.44494223422372936 -0.9999999999999996 0.44494223422372936 + -1.0 -8.368282382286802e-48 4.331468517193571e-16 + -1.1157709843049066e-47 + #KIT-Test-Building-01_LR.z42J72DCA0DG7fsjO1iJ + + + + + + + + + textures/Roofing_Shingles_GAF_Estates.jpg + wrap + + + #KIT-Test-Building-01_PG.as933cYedpVOQ8Wqm9j7 + + + 21.47458840372227 18.00558453022584 + 1.8506199769767277e-15 18.00558453022584 + -1.2918958832001822e-15 4.124469685250767 21.47458840372227 + 4.124469685250767 21.47458840372227 18.00558453022584 + #KIT-Test-Building-01_LR.FJ2G4jJFUVmWcdGG3gyw + + + + + + + #KIT-Test-Building-01_PG.CUXCVrNXAnCgCUjdXnY1 + + + -2.0055287249601352e-15 + -2.816087737236785 -21.47458840372227 -2.816087737236785 + -21.47458840372227 -16.697202582211872 + 1.8024740244805496e-15 -16.697202582211872 + -2.0055287249601352e-15 -2.816087737236785 + #KIT-Test-Building-01_LR.cYvvi9l6K4nl9jeHjt03 + + + + + + + + + textures/FZK-Haus-Back.png + wrap + + + #KIT-Test-Building-01_PG.cdHLpEJXgkf3Hq9x6PF7 + + + -1.0000000000000002 1.000011046207795 + -1.0000000000000002 0.7987000468203566 + 2.7071678232459823e-16 0.7987000468203567 + 3.007964248051091e-16 1.000011046207795 -1.0000000000000002 + 1.000011046207795 + #KIT-Test-Building-01_LR.ODQPptDGkQ9xxB6LArAA + + + + + + + #KIT-Test-Building-01_PG.Y4DuK1eWWjbSOQxjL75Z + + + 3.0079642480510913e-16 + -1.4416909618544142e-15 2.707167823245983e-16 + 0.7987000468203463 -1.0000000000000002 0.7987000468203463 + -1.0000000000000002 -1.4416909618544138e-15 + 3.0079642480510913e-16 -1.4416909618544142e-15 + #KIT-Test-Building-01_LR.CvfxHmYhr7DvEJeZnfKH + + + + + + + + + 0.2 + 0.4666666666666667 0.34509803921568627 + 0.21176470588235294 + 0.0 0.0 0.0 + 1.0 1.0 1.0 + 0.2 + 0.0 + false + #KIT-Test-Building-01_PG.B9OH2yr4U3AkPsKWbFy2 + + + + + diff --git a/CityDoctorParent/CityDoctorValidation/pom.xml b/CityDoctorParent/CityDoctorValidation/pom.xml index 48329e28a6d195e3d605b2a8052b3adceae93f8a..6cd0386295bb343dc7714a176c38058d7581c16f 100644 --- a/CityDoctorParent/CityDoctorValidation/pom.xml +++ b/CityDoctorParent/CityDoctorValidation/pom.xml @@ -4,7 +4,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 CityDoctorValidation CityDoctorValidation diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidation.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidation.java index 5b73190bff2699949f020a921782e01e5d369988..ec2d0df09e0c2e858d747670c34b9df74f5b79d7 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidation.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidation.java @@ -21,13 +21,11 @@ package de.hft.stuttgart.citydoctor2; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.file.Path; import java.util.List; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive; +import de.hft.stuttgart.citydoctor2.utils.Localization; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.citygml4j.core.ade.ADEException; import de.hft.stuttgart.citydoctor2.check.Checker; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; @@ -83,12 +81,12 @@ public class CityDoctorValidation { if (optional) { return null; } - logger.error("No output file specified. (-out [FILE])"); + logger.error(Localization.getText("CityDoctorValidation.noOutputFile")); System.exit(11); } List outFiles = argParser.getValues("out"); if (outFiles.size() != 1) { - logger.error("Specify exactly one file as output."); + logger.error(Localization.getText("CityDoctorValidation.notExactlyOneOutputFile")); System.exit(12); } outputFile = outFiles.get(0); @@ -157,15 +155,13 @@ public class CityDoctorValidation { ValidationConfiguration config, String outputFile) throws CityDoctorWriteException, CityGmlParseException, IOException, InvalidGmlFileException { File inputFile = new File(input); if (!inputFile.exists()) { - logger.error("Input file '{}' does not exist.", input); + logger.error(Localization.getText("CityDoctorValidation.inputFileNotExisting"), input); System.exit(1); } if (inputFile.getName().endsWith(".gml") || inputFile.getName().endsWith(".xml")) { startFileValidation(inputFile, xmlOutput, pdfOutput, config, outputFile); - } else if (inputFile.getName().endsWith(".zip")) { - startZipValidation(input, xmlOutput, pdfOutput, config, outputFile); } else { - logger.error("Input file '{}' does not end with .gml or .xml and is not a zip archive.", input); + logger.error(Localization.getText("CityDoctorValidation.wrongInputFileFormat"), input); System.exit(1); } } @@ -179,10 +175,11 @@ public class CityDoctorValidation { * @param pdfOutput the output path for the pdf report (optional) * @param config the configuration path for the validation plan * @param outputFile storing the validated gml file with quality ade - * @throws CityDoctorWriteException if something goes wrong while writing the gml - * file - * @throws CityGMLBuilderException - * @throws ADEException + * + * @throws IOException When an exception while writing the report files happens. + * @throws CityGmlParseException When an error while parsing the cityGML file happens. + * @throws InvalidGmlFileException If the cityGML file is not valid according to the cityGML schema. + * @throws CityDoctorWriteException If something goes wrong while writing the output gml file */ public static void startFileValidation(File inputFile, String xmlOutput, String pdfOutput, ValidationConfiguration config, String outputFile) throws IOException, CityGmlParseException, @@ -201,34 +198,11 @@ public class CityDoctorValidation { } } - public static void startZipValidation(String inputZipFile, String xmlOutput, String pdfOutput, - ValidationConfiguration config, String outputFile) throws CityGmlParseException, IOException { - xmlOutput = toDirectoryPath(xmlOutput); - pdfOutput = toDirectoryPath(pdfOutput); - outputFile = toDirectoryPath(outputFile); - if (xmlOutput == null && pdfOutput == null && outputFile == null) { - logger.warn("No output locations specified, results of validation will not be saved"); - } - CityGmlZipArchive archive = CityGmlZipArchive.register(inputZipFile); - Checker.streamCheck(archive, xmlOutput, pdfOutput, config, outputFile); - } - - public static String toDirectoryPath(String input) { - if (input == null) { - return null; - } - String parentDirectory = Path.of(input).getParent().toString() + File.separator; - String name = Path.of(input).getFileName().toString().replaceFirst("\\..+", "") + File.separator; - File f = new File(parentDirectory + name); - f.mkdir(); - return f.getPath() + File.separator; - } - public static String getPdfOutput(ArgumentParser argParser) { if (argParser.containsOption("pdfreport")) { List reportFiles = argParser.getValues("pdfreport"); if (reportFiles.size() != 1) { - logger.error("Specify exactly one file as pdfReport"); + logger.error(Localization.getText("CityDoctorValidation.notExactlyOnePDFOutput")); System.exit(6); } return reportFiles.get(0); @@ -240,7 +214,7 @@ public class CityDoctorValidation { if (argParser.containsOption("xmlreport")) { List reportFiles = argParser.getValues("xmlreport"); if (reportFiles.size() != 1) { - logger.error("Specify exactly one file as xmlReport"); + logger.error(Localization.getText("CityDoctorValidation.notExactlyOneXMLOutput")); System.exit(5); } return reportFiles.get(0); @@ -257,16 +231,16 @@ public class CityDoctorValidation { if (argParser.containsOption("config")) { List configFiles = argParser.getValues("config"); if (configFiles.size() != 1) { - logger.error("Specify exactly one file as configuration"); + logger.error(Localization.getText("CityDoctorValidation.notExactlyOneConfigFile")); System.exit(4); } return ValidationConfiguration.loadValidationConfig(configFiles.get(0)); } else { if (optional) { - logger.warn("No configuration file given, loading default configuration"); + logger.warn(Localization.getText("CityDoctorValidation.loadingDefaultConfig")); return ValidationConfiguration.loadStandardValidationConfig(); } else { - logger.error("No configuration file specified with -config [FILE]"); + logger.error(Localization.getText("CityDoctorValidation.noConfig")); System.exit(7); return null; } @@ -278,7 +252,7 @@ public class CityDoctorValidation { if (argParser.containsOption("out")) { List outFiles = argParser.getValues("out"); if (outFiles.size() != 1) { - logger.error("Specify exactly one file as output."); + logger.error(Localization.getText("CityDoctorValidation.multipleOutputFiles")); System.exit(3); } return outFiles.get(0); @@ -297,12 +271,12 @@ public class CityDoctorValidation { if (optional) { return null; } - logger.error("No input file specified. (-in [FILE])"); + logger.error(Localization.getText("CityDoctorValidation.noInputFile")); System.exit(1); } List inFiles = argParser.getValues("in"); if (inFiles.size() != 1) { - logger.error("Specify exactly one file as input."); + logger.error(Localization.getText("CityDoctorValidation.notExactlyOneInputFile")); System.exit(2); } inputFile = inFiles.get(0); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidationCLI.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidationCLI.java index 505c5eb54a7d32e60cee219350bb1795a859868f..9003eb7b97bcfeb67cafb5f0ae002312cfa46af8 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidationCLI.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/CityDoctorValidationCLI.java @@ -1,12 +1,19 @@ package de.hft.stuttgart.citydoctor2; -import java.util.concurrent.Callable; +import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; +import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; +import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; +import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; +import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Option; +import java.io.File; +import java.io.IOException; + @Command(name = "citydoctor2", mixinStandardHelpOptions = true, description = "Validates CityGML files according to a provided validation-plan.") -public class CityDoctorValidationCLI implements Callable { +public class CityDoctorValidationCLI implements Runnable { @Option(names = {"-i" , "--in" , "--input"}, description = "Filepath of the CityGML file.", @@ -15,23 +22,41 @@ public class CityDoctorValidationCLI implements Callable { @Option(names = {"-c" , "--config" , "--configuration", "--plan"}, description = "Filepath of the validation configuration .yml", - required = true) - private String config; + defaultValue = Option.NULL_VALUE) + private File config; @Option(names = {"-x" , "--xml" , "--xmlReport"}, - description = "Create a XML validation report at target location") + description = "Create a XML validation report at target location", + defaultValue = Option.NULL_VALUE) private String xmlReport; @Option(names = {"-p" , "--pdf" , "--pdfReport"}, - description = "Create a PDF validation report at target location") + description = "Create a PDF validation report at target location", + defaultValue = Option.NULL_VALUE) private String pdfReport; @Option(names = {"-o" , "--out" , "--output"}, - description = "Create a validated copy of the CityGML input with QualityADE at target location.") + description = "Create a validated copy of the CityGML input with QualityADE at target location.", + defaultValue = Option.NULL_VALUE) private String output; @Override - public Integer call() throws Exception { - return 0; + public void run(){ + try { + ValidationConfiguration valConfig; + if(config == null){ + valConfig=ValidationConfiguration.loadStandardValidationConfig(); + } else{ + valConfig=ValidationConfiguration.loadValidationConfig(config.getAbsolutePath()); + } + CityDoctorValidation.startValidationProcess(input, xmlReport, pdfReport, valConfig,output); + } catch (CityDoctorWriteException | CityGmlParseException | IOException | InvalidGmlFileException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + int exitCode = new CommandLine(new CityDoctorValidationCLI()).execute(args); + System.exit(exitCode); } } diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java index 38bd869f4583418c97ac011d009f027a646ca601..c863720e40b70668737309eaa2148ce5cc42e9f4 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java @@ -28,9 +28,14 @@ import de.hft.stuttgart.citydoctor2.checks.CheckPrototype; import de.hft.stuttgart.citydoctor2.checks.Checks; import de.hft.stuttgart.citydoctor2.checks.SvrlContentHandler; import de.hft.stuttgart.citydoctor2.checks.util.FeatureCheckedListener; +import de.hft.stuttgart.citydoctor2.database.CityObjectCache; +import de.hft.stuttgart.citydoctor2.database.CityObjectCache; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; +import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder; +import de.hft.stuttgart.citydoctor2.datastructure.GmlId; import de.hft.stuttgart.citydoctor2.parser.CityGmlConsumer; import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; @@ -42,11 +47,8 @@ import de.hft.stuttgart.citydoctor2.reporting.XmlStreamReporter; import de.hft.stuttgart.citydoctor2.reporting.XmlValidationReporter; import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfReporter; import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfStreamReporter; -import de.hft.stuttgart.citydoctor2.utils.ArchivePacker; 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.CityGmlZipEntryFile; +import de.hft.stuttgart.citydoctor2.utils.TimeFormatter; import de.hft.stuttgart.quality.model.enums.RequirementId; import de.hft.stuttgart.quality.model.enums.TopLevelFeatureType; import de.hft.stuttgart.quality.model.properties.CheckingProperty; @@ -57,7 +59,6 @@ import de.hft.stuttgart.quality.model.properties.RequirementProperty; import de.hft.stuttgart.quality.model.types.Checking; import de.hft.stuttgart.quality.model.types.Parameter; import de.hft.stuttgart.quality.model.types.ValidationPlan; -import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -79,6 +80,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; @@ -89,7 +91,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.stream.Stream; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; /** * The main container class for checking. It contains the logic for validation, @@ -191,18 +194,46 @@ public class Checker { if (config == null) { config = ValidationConfiguration.loadStandardValidationConfig(); } - checkCityModel(model, l); - if (logger.isInfoEnabled()) { - logger.info(Localization.getText("Checker.checksFinished")); + AutoCloseable checkingContext = model.getCache().startCheckingMode(); + try(checkingContext){ + Callable schematronThread = () -> executeSchematronValidationIfAvailable(config, model.getFile()); + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future handlerFuture = executor.submit(schematronThread); + executor.shutdown(); + + checkCityModel(model, l); + getSchematronResults(handlerFuture, l); + + model.setValidated(createValidationPlan()); + } catch (Exception e){ + logger.error("Validation failed due to encountering error", e); } - SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, model.getFile()); - if (handler != null) { - handleSchematronResults(handler); + } + + private void getSchematronResults(Future handlerFuture, ProgressListener l) { + if (!handlerFuture.isDone()) { + if (logger.isInfoEnabled()) { + logger.info(Localization.getText("Checker.schematronStillRunning")); + } + if(l !=null){ + l.updateProgress(-0.5f); + } + } + try { + SvrlContentHandler handler = handlerFuture.get(); + if (handler != null) { + handleSchematronResults(handler); + } + } catch (ExecutionException e) { + logger.error(e); + } catch (InterruptedException e) { + logger.error(Localization.getText("Checker.schematronInterrupted"), e); + Thread.currentThread().interrupt(); } - model.setValidated(createValidationPlan()); } private void handleSchematronResults(SvrlContentHandler handler) { + CityObjectCache cache = model.getCache(); handleSchematronErrorsGlobal(handler.getGeneralErrors()); Map featureMap = new HashMap<>(); boolean onlySchematron = execLayers.isEmpty(); @@ -222,7 +253,7 @@ public class Checker { } handler.getFeatureErrors().forEach((k, v) -> { String trimmedId = k.trim(); - CityObject co = featureMap.get(trimmedId); + CityObject co = cache.get(new GmlId(k)); if (co == null) { // gml id reported by schematron was not found, add to general errors handleSchematronErrorsGlobal(v); @@ -468,6 +499,10 @@ public class Checker { if (logger.isInfoEnabled()) { logger.info(Localization.getText("Checker.schematronValidation")); } + if (!Files.exists(Path.of(config.getSchematronFilePath()))) { + logger.warn(Localization.getText("Checker.schematronFileNotFound"), config.getSchematronFilePath()); + return null; + } try { TransformerFactory transformerFactory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", Checker.class.getClassLoader()); @@ -585,7 +620,7 @@ public class Checker { for (Entry e : config.getRequirements().entrySet()) { de.hft.stuttgart.citydoctor2.check.Requirement req = Checks.getAvailableRequirements().get(e.getKey()); if (req == null) { - logger.warn("Could not find any check that satisfies requirement {}, it will not be checked", + logger.warn(Localization.getText("Checker.noCheckSatisfiesRequirement"), e.getKey()); } else { if (e.getValue().isEnabled()) { @@ -652,31 +687,110 @@ public class Checker { } } - private void checkCityModel(CityDoctorModel model, ProgressListener l) { - Stream features = model.createFeatureStream(); - float featureSum = model.getNumberOfFeatures(); + private void checkCityModel(CityDoctorModel model, ProgressListener l){ + List features = model.getFeatureIds(); + + AtomicInteger checkedCount = new AtomicInteger(0); // clear global errors model.getGlobalErrors().clear(); - - // stupid lamda with final variable restrictions - int[] currentFeature = new int[1]; - features.forEach(co -> { - if (config.getParserConfiguration().useLowMemoryConsumption()) { - // no edges have been created yet, create them - co.prepareForChecking(); + CityObjectCache cache = model.getCache(); + logger.trace("Setting up ThreadPool"); + int threadCount = Runtime.getRuntime().availableProcessors() * 5; + ExecutorService exec = new ThreadPoolExecutor + (threadCount, threadCount, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); + try{ + long startTime = System.nanoTime(); + ImplicitGeometryHolder.preparePrototypeGeometriesForChecking(); + + List> futures = runChecksOnFeatures(exec, cache, features, checkedCount, l); + List missedFeatures = getMissedFeatures(futures); + + ImplicitGeometryHolder.clearMetaDataOfPrototypeGeometries(); + if (!missedFeatures.isEmpty()){ + logger.error(Localization.getText("Checker.dbUnresponsive")); + if (logger.isDebugEnabled()){ + logger.debug(missedFeatures.toString()); + } } - // check every feature - executeChecksForCityObject(co); + long endTime = System.nanoTime(); + if (logger.isInfoEnabled()){ + long totalTime = (endTime - startTime) / 1_000_000; // Convert ns to ms + String messageString = Localization.getText("Checker.checksFinished"); + String timeString = TimeFormatter.format(totalTime); + messageString = messageString.replace("{0}", timeString); + logger.info(messageString); + } + } catch (InterruptedException e){ + // No interrupts implemented, so this block should actually never be entered + logger.error(Localization.getText("Checker.validationInterrupted"), e); + Thread.currentThread().interrupt(); + + } finally { + exec.shutdown(); + try { + if(!exec.awaitTermination(1, TimeUnit.MINUTES)){ + exec.shutdownNow(); + } - if (config.getParserConfiguration().useLowMemoryConsumption()) { - // low memory consumption, remove edges again - co.clearMetaInformation(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + logger.error(Localization.getText("Checker.shutdownInterrupted")); } - if (l != null) { - currentFeature[0]++; - l.updateProgress(currentFeature[0] / featureSum); + } + } + + private List> runChecksOnFeatures(ExecutorService exec, CityObjectCache cache, List ids, AtomicInteger checkedCount, + ProgressListener l) + throws InterruptedException { + float featureSum = ids.size() + (float) checkedCount.get(); + + logger.trace("Queueing up Checker tasks"); + List> tasks = new ArrayList<>(); + for (GmlId id : ids) { + tasks.add(()->{ + CityObject co = cache.get(id); + if (co == null) { + return id; + } + if(Thread.interrupted()){ + Thread.currentThread().interrupt(); + return null; + } + co.prepareForChecking(); + executeChecksForCityObject(co); + co.clearMetaInformation(); + cache.put(co); + checkedCount.incrementAndGet(); + if (l!=null){ + l.updateProgress((checkedCount.get()) / featureSum); + } + return null; + }); + } + logger.trace("Queueing up finished, invoking all tasks"); + return exec.invokeAll(tasks); + } + + private List getMissedFeatures(List> futures) throws InterruptedException{ + List missedList = new ArrayList<>(); + Set errors = new HashSet<>(); + for (Future future : futures) { + try{ + GmlId gmlId = future.get(); + if (gmlId != null) { + missedList.add(gmlId); + } + } catch (ExecutionException e){ + logger.debug("A Task failed due to an unexpected exception", e); + logger.debug(e.getCause()); + errors.add(e); } - }); + } + if (!errors.isEmpty()) { + logger.error(Localization.getText("Checker.futuresCheckFailures")); + logger.error(errors.toString()); + } + return missedList; } private boolean filterObject(CityObject co) { @@ -782,73 +896,6 @@ public class Checker { return hasUnusedDependency; } - public static void streamCheck(CityGmlZipArchive archive, String xmlDirectory, String pdfDirectory, ValidationConfiguration config, - String outputDirectory) throws IOException, CityGmlParseException { - streamCheck(archive, xmlDirectory, pdfDirectory, config, null, outputDirectory); - } - - public static void streamCheck(CityGmlZipArchive archive, String xmlDirectory, String pdfDirectory, ValidationConfiguration config, - FeatureCheckedListener l, String outputDirectory) throws IOException, CityGmlParseException { - - - for (CityGmlZipEntry entry : archive.getEntries()) { - String entryName = FilenameUtils.removeExtension(entry.getDisplayName()); - String xmlOutput = null; - String pdfOutput = null; - String outputFile = null; - if (xmlDirectory != null) { - xmlOutput = Path.of(xmlDirectory).resolve(entryName + "_report.xml").toString(); - } - if (pdfDirectory != null) { - pdfOutput = Path.of(pdfDirectory).resolve(entryName + "_report.pdf").toString(); - } - if (outputDirectory != null) { - outputFile = Path.of(outputDirectory).resolve(entryName + "_validated.gml").toString(); - } - - streamCheck(entry, xmlOutput, pdfOutput, config, l, outputFile); - - - } - if (outputDirectory != null) { - ArchivePacker.packAndDeleteDirectory(outputDirectory); - } - } - - - public static void streamCheck(CityGmlZipEntry entry, String xmlOutput, String pdfOutput, ValidationConfiguration config, - String outputFile) throws IOException, CityGmlParseException { - streamCheck(entry, xmlOutput, pdfOutput, config, null, outputFile); - } - - public static void streamCheck(CityGmlZipEntry entry, String xmlOutput, String pdfOutput, ValidationConfiguration config, - FeatureCheckedListener l, String outputFile) throws IOException, CityGmlParseException { - try (BufferedOutputStream xmlBos = getXmlOutputMaybe(xmlOutput); - BufferedOutputStream pdfBos = getPdfOutputMaybe(pdfOutput)) { - Checker c = new Checker(config, null); - String fileName = entry.getEntrySubPath(); - - // create reporter if available - XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName); - PdfStreamReporter pdfReporter = getPdfReporter(config, pdfBos, fileName); - - // execute schematron first - try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) { - SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, entryFile.getInputStream()); - - CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, l); - // parse and validate - CityGmlParser.streamCityGml(entry, config.getParserConfiguration(), con, outputFile); - - // write reports if available - writeReport(xmlReporter); - writeReport(pdfReporter); - } - } catch (CheckReportWriteException e) { - logger.error(Localization.getText("Checker.failReports"), e); - } - } - public static void streamCheck(File inputFile, String xmlOutput, String pdfOutput, ValidationConfiguration config, String outputFile) throws IOException, CityGmlParseException { streamCheck(inputFile, xmlOutput, pdfOutput, config, null, outputFile); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java index c3ff365c3980e47e729bb0d2d940938cd3dcb7f0..1c542e653354490735d652f30f8ecf3f81f39d64 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/StreamCityGmlConsumer.java @@ -134,7 +134,7 @@ public class StreamCityGmlConsumer implements CityGmlConsumer { pdfReporter.report(co); } - // TODO: Update QualityADE to be compatible with CityGML 3.0 or deprecate it, unhandled top-level feature types are just skipped for now + // TODO: Update QualityADE to be compatible with CityGML 3.0, unhandled top-level feature types are just skipped for now if (!(co instanceof AbstractTunnel || co instanceof CityFurniture || co instanceof GenericCityObject)) { // store quality ade datastructures in cityobject QualityADEUtils.writeQualityAde(co, val); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckContainer.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckContainer.java index 8b6f2943b8f19e88a65a52fe5c41eca1cdf9ea00..7e628940ea3053a8e1dc3ff0d15d9586bde08e4c 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckContainer.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/CheckContainer.java @@ -230,6 +230,24 @@ public class CheckContainer extends Check { } } + @Override + public void check(TinObject to) { + try { + check.check(to); + }catch (Exception e) { + handleException(e, to); + } + } + + @Override + public void check(ReliefObject ro) { + try { + check.check(ro); + }catch (Exception e) { + handleException(e, ro); + } + } + @Override public void check(CityFurniture cf){ try { @@ -248,6 +266,15 @@ public class CheckContainer extends Check { } } + @Override + public void check(OtherConstructionObject oco) { + try { + check.check(oco); + }catch (Exception e) { + handleException(e, oco); + } + } + @Override public RequirementType getType() { return check.getType(); diff --git a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java index 5bf19ad3c957cb2495c1e5c27316175d1dac80f0..3c5503835fda1730e561ff6d7e6d8668c6933dcc 100644 --- a/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java +++ b/CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/reporting/XmlValidationReporter.java @@ -45,33 +45,8 @@ public class XmlValidationReporter implements Reporter { @Override public void writeReport(Checks checks, OutputStream filePath, CityDoctorModel model, ValidationConfiguration config) throws CheckReportWriteException { StreamReporter streamReporter = new XmlStreamReporter(filePath, model.getFileName(), config); - for (BridgeObject bo : model.getBridges()) { - streamReporter.report(bo); - } - for (Building b : model.getBuildings()) { - streamReporter.report(b); - } - for (TransportationObject to : model.getTransportation()) { - streamReporter.report(to); - } - for (CityObject lo : model.getLand()) { - streamReporter.report(lo); - } - for (Vegetation v : model.getVegetation()) { - streamReporter.report(v); - } - for (WaterObject wo : model.getWater()) { - streamReporter.report(wo); - } - for (Tunnel tunnel : model.getTunnels()) { - streamReporter.report(tunnel); - } - for (CityFurniture cf : model.getCityFurniture()) { - streamReporter.report(cf); - } - for (GenericCityObject gco : model.getGenericCityObjects()) { - streamReporter.report(gco); - } + model.createFeatureStream().forEach(streamReporter::report); + for (CheckError err : model.getGlobalErrors()) { streamReporter.reportGlobalError(err); } diff --git a/CityDoctorParent/CityDoctorValidation/src/main/resources/log4j2.xml b/CityDoctorParent/CityDoctorValidation/src/main/resources/log4j2.xml new file mode 100644 index 0000000000000000000000000000000000000000..1b1a09f31c1dea7e13e9f9a70aa5b80703e4a8d0 --- /dev/null +++ b/CityDoctorParent/CityDoctorValidation/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java index 799b27307361491671017a36ef2a3b328ef713dd..cbc489abf908279d7d8e193f47b2db258495141b 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java @@ -24,7 +24,6 @@ import de.hft.stuttgart.citydoctor2.checkresult.GlobalErrorStatistics; import de.hft.stuttgart.citydoctor2.checkresult.GlobalStatistics; import de.hft.stuttgart.citydoctor2.checkresult.ModelStatistics; import de.hft.stuttgart.citydoctor2.checkresult.utility.CheckReportParseException; -import de.hft.stuttgart.citydoctor2.checks.util.FeatureCheckedListener; import de.hft.stuttgart.citydoctor2.datastructure.Building; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException; @@ -32,8 +31,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipArchive; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry; import org.apache.commons.io.FileUtils; import org.junit.Rule; import org.junit.Test; @@ -68,7 +65,7 @@ public class CheckerTest { "src/test/resources/SimpleSolid_SrefBS_SchematronTest.gml", config.getParserConfiguration()); Checker checker = new Checker(config, model); checker.runChecks(); - for (Building b : model.getBuildings()) { + for (Building b : model.getBuildings().toList()) { if (b.getGmlId().getGmlString().equals("_Simple_BD.1")) { assertTrue(b.containsAnyError()); } else { @@ -128,76 +125,6 @@ public class CheckerTest { } } - @Test - public void testCliZipChecking() throws IOException, CityDoctorWriteException, CityGmlParseException, InvalidGmlFileException { - String output = folder.getRoot().toPath() + File.separator + "test"; - String pdfOutput = folder.getRoot().toPath() + File.separator + "pdf" + File.separator; - String xmlOutput = folder.getRoot().toPath() + File.separator + "xml" + File.separator; - try { - String[] args = new String[10]; - args[0] = "-in"; - args[1] = "src/test/resources/zipArchive.zip"; - args[2] = "-config"; - args[3] = "src/test/resources/testConfigWithStreaming.yml"; - args[4] = "-pdfReport"; - args[5] = pdfOutput; - args[6] = "-xmlReport"; - args[7] = xmlOutput; - args[8] = "-out"; - args[9] = output + File.separator; - CityDoctorValidation.main(args); - File zipFile = new File(output + ".zip"); - File pdfDir = new File(pdfOutput); - File xmlDir = new File(xmlOutput); - assertTrue(zipFile.exists()); - assertTrue(pdfDir.exists()); - assertTrue(xmlDir.exists()); - - assertTrue(pdfDir.isDirectory()); - assertTrue(xmlDir.isDirectory()); - assertEquals(5, pdfDir.listFiles().length); - assertEquals(5, xmlDir.listFiles().length); - - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register(output + ".zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(new ParserConfiguration(8, true)); - assertEquals(5, cgmlArch.getEntries().size()); - for (CityGmlZipEntry entry : cgmlArch.getEntries()) { - assertNotNull(entry); - assertNull(entry.getErrorType()); - } - - } catch (CityGmlParseException | IOException | InvalidGmlFileException | CityDoctorWriteException e) { - throw e; - } - } - - @Test - public void testZipEntryChecking() throws CityGmlParseException, IOException { - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zipArchive.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(new ParserConfiguration(8, false)); - ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig(); - FeatureCheckedListener l = co -> { - assertTrue("CityObject should be validated", co.isValidated()); - }; - for (CityGmlZipEntry entry : cgmlArch.getEntries()) { - Checker.streamCheck(entry, null, null, config, l, null); - } - } - - @Test - public void testZipArchiveChecking() throws CityGmlParseException, IOException { - CityGmlZipArchive cgmlArch = CityGmlZipArchive.register("src/test/resources/zipArchive.zip"); - assertNotNull(cgmlArch); - cgmlArch.mountArchive(new ParserConfiguration(8, false)); - ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig(); - FeatureCheckedListener l = co -> { - assertTrue(co.isValidated()); - }; - Checker.streamCheck(cgmlArch, null, null, config, l, null); - } - @Test public void testReportCreation() throws IOException, CityGmlParseException, InvalidGmlFileException { Path tmpDir = null; @@ -207,7 +134,7 @@ public class CheckerTest { Path xmlPath = tmpDir.resolve("report.xml"); Path pdfPath = tmpDir.resolve("report.pdf"); File features = new File("src/test/resources/feature_types.gml"); - CityDoctorModel model = CityGmlParser.parseCityGmlFileSilently( + CityDoctorModel model = CityGmlParser.nestedCityGmlFileParse( features.toString(), new ParserConfiguration(8, false)); assertNotNull(model); Checker checker = new Checker(model); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/FilterTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/FilterTest.java index f3c096f0b3cb08f021f194840600b68a3ebb98bf..b8c2d3674a44ca8bef7df547432184510de971bd 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/FilterTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/FilterTest.java @@ -45,12 +45,12 @@ public class FilterTest { Checker c = new Checker(config, model); c.runChecks(); - Building b = model.getBuildings().get(0); + Building b = model.getBuildings().toList().get(0); Geometry geom = b.getGeometries().get(0); assertFalse(geom.hasCheckResults()); - TransportationObject to = model.getTransportation().get(0); + TransportationObject to = model.getTransportation().toList().get(0); Geometry geom2 = to.getGeometries().get(0); assertTrue(geom2.getPolygons().get(0).hasCheckResults()); @@ -65,12 +65,12 @@ public class FilterTest { Checker c = new Checker(config, model); c.runChecks(); - Building b = model.getBuildings().get(0); + Building b = model.getBuildings().toList().get(0); Geometry geom = b.getGeometries().get(0); assertFalse(geom.hasCheckResults()); - TransportationObject to = model.getTransportation().get(0); + TransportationObject to = model.getTransportation().toList().get(0); Geometry geom2 = to.getGeometries().get(0); assertTrue(geom2.getPolygons().get(0).hasCheckResults()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/DegeneratedPolygonCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/DegeneratedPolygonCheckTest.java index 98669c4056f985bc14c0f1e834afb584f6182bb3..7859eb72d23b80b5b4586048b7297afc1b6ce733 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/DegeneratedPolygonCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/DegeneratedPolygonCheckTest.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import de.hft.stuttgart.citydoctor2.database.UnconnectedCache; import org.junit.Test; import de.hft.stuttgart.citydoctor2.check.CheckError; @@ -44,6 +45,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Geometry.Orientation; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.quality.model.enums.RequirementId; +import org.mockito.Mockito; public class DegeneratedPolygonCheckTest { @@ -68,9 +70,10 @@ public class DegeneratedPolygonCheckTest { Building b = new Building(); b.addGeometry(geom); - + File file = Mockito.mock(File.class); + Mockito.when(file.getName()).thenReturn("building"); ParserConfiguration config = new ParserConfiguration(8, false); - CityDoctorModel model = new CityDoctorModel(config, new File("")); + CityDoctorModel model = new CityDoctorModel(config, file, new UnconnectedCache()); model.addBuilding(b); ValidationConfiguration valConfig = ValidationConfiguration.loadStandardValidationConfig(); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckFalsePositiveBigMeshTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckFalsePositiveBigMeshTest.java index d79fed452bec668bfba03968c8bb20f24ddfde8a..20ad29a1dc48c0afc2920fb491255a60f414d072 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckFalsePositiveBigMeshTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckFalsePositiveBigMeshTest.java @@ -35,7 +35,7 @@ public class SolidSelfIntCheckFalsePositiveBigMeshTest { CityDoctorModel m = CityGmlParser.parseCityGmlFile(gml_filepath, config.getParserConfiguration()); Checker c = new Checker(config, m); c.runChecks(); - Building building = m.getBuildings().get(0); + Building building = m.getBuildings().toList().get(0); /* * The examples have no actual self-intersections, but can contain other actual model defects. * If an error is detected, it is thus required to check if the diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckTest.java index d31e6c8babac3c4f437ff2707f0c04a2f6aa03ab..7531268e16c20e9ad90704c0258859877af339ac 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheckTest.java @@ -95,7 +95,7 @@ public class SolidSelfIntCheckTest { CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/SolidSelfIntTest1.gml", config.getParserConfiguration()); Checker c = new Checker(config, m); c.runChecks(); - assertFalse(m.getBuildings().get(0).containsAnyError()); + assertFalse(m.getBuildings().toList().get(0).containsAnyError()); } @@ -105,7 +105,7 @@ public class SolidSelfIntCheckTest { CityDoctorModel m = CityGmlParser.parseCityGmlFile(gml_filepath, config.getParserConfiguration()); Checker c = new Checker(config, m); c.runChecks(); - Building building = m.getBuildings().get(0); + Building building = m.getBuildings().toList().get(0); /* * The examples have no actual self-intersections, but can contain other actual model defects. * If an error is detected, it is thus required to check if the diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/AllPolygonWrongOrientedTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/AllPolygonWrongOrientedTest.java index e941df1946461dc80fc2d51912529b4e535f4cf5..e96b4e45f807843d4c9e921572e605cc9184e136 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/AllPolygonWrongOrientedTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/AllPolygonWrongOrientedTest.java @@ -48,7 +48,7 @@ public class AllPolygonWrongOrientedTest { Checker c = new Checker(config, model); c.runChecks(); - Building b = model.getBuildings().get(0); + Building b = model.getBuildings().toList().get(0); assertFalse(b.containsError(CheckId.C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION)); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ConCompCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ConCompCheckTest.java index 2a8c1317fd1397912446ca11abac4c2e899376f1..b9a508095bc3da244bc2e932b787c30a976fc877 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ConCompCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ConCompCheckTest.java @@ -51,7 +51,7 @@ public class ConCompCheckTest extends TestCleanUp { Checker c = new Checker(m); c.runChecks(); - Geometry geom = m.getBuildings().get(0).getGeometries().get(0); + Geometry geom = m.getBuildings().toList().get(0).getGeometries().get(0); CheckResult cr = geom.getCheckResult(CheckId.C_GE_S_MULTIPLE_CONNECTED_COMPONENTS); assertNotNull(cr); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); @@ -65,7 +65,7 @@ public class ConCompCheckTest extends TestCleanUp { Checker c = new Checker(m); c.runChecks(); - Geometry geom = m.getBuildings().get(0).getGeometries().get(0); + Geometry geom = m.getBuildings().toList().get(0).getGeometries().get(0); CheckResult cr = geom.getCheckResult(CheckId.C_GE_S_MULTIPLE_CONNECTED_COMPONENTS); assertNotNull(cr); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/DupPointsCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/DupPointsCheckTest.java index 924c651ee8c38889a9f2887df4176de0c6475883..2720b0114a11b59726ebc232f82d8d92b3261b53 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/DupPointsCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/DupPointsCheckTest.java @@ -79,7 +79,7 @@ public class DupPointsCheckTest { @Test public void testDupPoints3() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel m = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS.gml"); - for (Polygon p : m.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : m.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { LinearRing r = p.getExteriorRing(); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_DUPLICATE_POINT); assertEquals(ResultStatus.OK, cr.getResultStatus()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/HoleOutsideSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/HoleOutsideSystemTest.java index 89072edcdf00906f4b6635788ae09b49ad4b85dc..dd603053ca7d71ec338650570a4989b8e03442c5 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/HoleOutsideSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/HoleOutsideSystemTest.java @@ -43,7 +43,7 @@ public class HoleOutsideSystemTest { @Test public void testHoleOutside1() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"); - for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_HOLE_OUTSIDE); assertEquals(ResultStatus.OK, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InnerRingsNestedSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InnerRingsNestedSystemTest.java index 6ae1d4784e4694fca61c2728298ab73ecfaae070..ca2982e97cb2eb608b6d5d647e73d5e8adf88178 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InnerRingsNestedSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InnerRingsNestedSystemTest.java @@ -43,7 +43,7 @@ public class InnerRingsNestedSystemTest { @Test public void innerRingsNested1() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"); - for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_INNER_RINGS_NESTED); assertEquals(ResultStatus.OK, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InteriorDisconnectedSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InteriorDisconnectedSystemTest.java index 4ddd49c4c80c84e52affbea83eb11ee17edffe3e..9d7ac4466eebb596fd1b1613417469896156535c 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InteriorDisconnectedSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/InteriorDisconnectedSystemTest.java @@ -43,7 +43,7 @@ public class InteriorDisconnectedSystemTest { @Test public void testInteriorDisconnected1() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"); - for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_INTERIOR_DISCONNECTED); assertEquals(ResultStatus.OK, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/MultipleComponentTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/MultipleComponentTest.java index 33aaafbd829182bd8152eb799c73c212f783bdaf..f958a9e023b454ea27fa45704913fc418fa23919 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/MultipleComponentTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/MultipleComponentTest.java @@ -43,7 +43,7 @@ public class MultipleComponentTest { @Test public void testNoMultipleComponents() throws CityGmlParseException, IOException, InvalidGmlFileException { 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_MULTIPLE_CONNECTED_COMPONENTS); assertEquals(ResultStatus.OK, cr.getResultStatus()); } @@ -51,7 +51,7 @@ public class MultipleComponentTest { @Test public void testMultipleComponents() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0005-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_MULTIPLE_CONNECTED_COMPONENTS); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ErrorId.GE_S_MULTIPLE_CONNECTED_COMPONENTS, cr.getError().getErrorId()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldEdgeSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldEdgeSystemTest.java index 66e121b26da26a57fe8ad9d8026d41cbfcefa56e..597bd46268887d78054d80c6a751f5e2d2bc3221 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldEdgeSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldEdgeSystemTest.java @@ -46,7 +46,7 @@ public class NonManifoldEdgeSystemTest { @Test public void testNonManifoldEdge1() throws CityGmlParseException, IOException, InvalidGmlFileException { 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_NON_MANIFOLD_EDGE); assertEquals(ResultStatus.OK, cr.getResultStatus()); } @@ -59,7 +59,7 @@ public class NonManifoldEdgeSystemTest { paramMap.put(RequirementId.R_GE_P_NON_PLANAR.toString(), parameter); CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml", paramMap); - 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_NON_MANIFOLD_EDGE); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ErrorId.GE_S_NON_MANIFOLD_EDGE, cr.getError().getErrorId()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldVertexSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldVertexSystemTest.java index 127745410d707602a3238b97d3f377516ed9bb0e..9ab2e229831157a09dd6652d0163384f88169fcd 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldVertexSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NonManifoldVertexSystemTest.java @@ -43,7 +43,7 @@ public class NonManifoldVertexSystemTest { @Test public void testNonManifoldVertex1() throws CityGmlParseException, IOException, InvalidGmlFileException { 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_NON_MANIFOLD_VERTEX); assertEquals(ResultStatus.OK, cr.getResultStatus()); } @@ -51,7 +51,7 @@ public class NonManifoldVertexSystemTest { @Test public void testNonManifoldVertex2() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0003-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_NON_MANIFOLD_VERTEX); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ErrorId.GE_S_NON_MANIFOLD_VERTEX, cr.getError().getErrorId()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NumPointsCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NumPointsCheckTest.java index 2a1a6b37d2d32728b0de55f5583988365cbc5225..22c2c426a3a148e5380d8b36992e0086f6e1904d 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NumPointsCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/NumPointsCheckTest.java @@ -80,7 +80,7 @@ public class NumPointsCheckTest { public void testNumPoints3() throws CityGmlParseException, IOException, InvalidGmlFileException { 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(); assertEquals(ResultStatus.OK, r.getCheckResult(CheckId.C_GE_R_TOO_FEW_POINTS).getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OrientationSameSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OrientationSameSystemTest.java index 687871312622bfb2d9e62a02b078ccb39272e1ce..1e3b3a5654224f008766778db5619aafc79af121 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OrientationSameSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OrientationSameSystemTest.java @@ -43,7 +43,7 @@ public class OrientationSameSystemTest { @Test public void testOrientationSame1() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"); - for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_ORIENTATION_RINGS_SAME); assertEquals(ResultStatus.OK, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OuterEdgeCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OuterEdgeCheckTest.java index 2b6af2fbd2a172f34a39a5514fc09cdc49535a99..08e88d65c4dcfaff34f514a871c7ec49b683a84c 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OuterEdgeCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/OuterEdgeCheckTest.java @@ -71,7 +71,7 @@ public class OuterEdgeCheckTest { expectedErrorEdges.add(new Vertex(1.0, 0.0, 3.5)); expectedErrorEdges.add(new Vertex(2.0, 0.0, 3.0)); - Geometry geom = m.getBuildings().get(0).getGeometries().get(0); + Geometry geom = m.getBuildings().toList().get(0).getGeometries().get(0); CheckResult cr = geom.getCheckResult(CheckId.C_GE_S_NOT_CLOSED); Assert.assertEquals(ResultStatus.ERROR, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PlanarTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PlanarTest.java index 0b3f2c725e8b19dae4f9095454796524aa65a3dc..34d69e7adf6cab6e945571b2308cb9a1d1ecbea9 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PlanarTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PlanarTest.java @@ -107,7 +107,7 @@ public class PlanarTest { @Test public void testPlanarPolygon3() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"); - for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_NON_PLANAR); assertEquals(ResultStatus.OK, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PolygonIntersectingRingsTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PolygonIntersectingRingsTest.java index a4dadfb38a6e97e1c956ef6cd60103e5860eb76c..a18ed09e06bc2c145e9dec3f36f4a0a7db8d5e8c 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PolygonIntersectingRingsTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/PolygonIntersectingRingsTest.java @@ -43,7 +43,7 @@ public class PolygonIntersectingRingsTest { @Test public void testSelfIntPolygon1() throws CityGmlParseException, IOException, InvalidGmlFileException { 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()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_INTERSECTING_RINGS); assertEquals(ResultStatus.OK, cr.getResultStatus()); } @@ -52,7 +52,7 @@ public class PolygonIntersectingRingsTest { @Test public void testSelfIntPolygon2() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"); - for (Polygon p : c.getBuildings().get(0).getGeometries().get(0).getPolygons()) { + for (Polygon p : c.getBuildings().toList().get(0).getGeometries().get(0).getPolygons()) { CheckResult cr = p.getCheckResult(CheckId.C_GE_P_INTERSECTING_RINGS); assertEquals(ResultStatus.OK, cr.getResultStatus()); } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingClosedCheckTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingClosedCheckTest.java index 7cdf629c77a367b0710818316998cda025922d23..9be6709e7073afe043ecd108f50b45cdb5cb11da 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingClosedCheckTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingClosedCheckTest.java @@ -91,7 +91,7 @@ public class RingClosedCheckTest extends TestCleanUp { @Test public void testClosedRing3() throws CityGmlParseException, IOException, InvalidGmlFileException { 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(); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_NOT_CLOSED); assertEquals(ResultStatus.OK, cr.getResultStatus()); @@ -111,7 +111,7 @@ public class RingClosedCheckTest extends TestCleanUp { @Test public void testClosedRing5() throws CityGmlParseException, IOException, InvalidGmlFileException { CityDoctorModel c = TestUtil.loadAndCheckCityModel("src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml", 1); - 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(); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_NOT_CLOSED); assertEquals(ResultStatus.OK, cr.getResultStatus()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingSelfIntersectionTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingSelfIntersectionTest.java index 9b9da948f78a732cdc34a8845c9eff50d0a0b7b0..76e04e9678c57217d1498bab03555ff071a4a200 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingSelfIntersectionTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/RingSelfIntersectionTest.java @@ -101,7 +101,7 @@ public class RingSelfIntersectionTest { @Test public void testSelfIntPoints4() throws CityGmlParseException, IOException, InvalidGmlFileException { 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(); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_SELF_INTERSECTION); assertEquals(ResultStatus.OK, cr.getResultStatus()); @@ -131,7 +131,7 @@ public class RingSelfIntersectionTest { @Test public void testSelfIntPoints7() throws CityGmlParseException, IOException, InvalidGmlFileException { 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(); CheckResult cr = r.getCheckResult(CheckId.C_GE_R_SELF_INTERSECTION); assertEquals(ResultStatus.OK, cr.getResultStatus()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ShellNotClosedSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ShellNotClosedSystemTest.java index e26695bc98e1efd20b3b4a24e5bc4ca679621f65..f51002491191f94c40fc8c6c78075c8b9c45fa94 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ShellNotClosedSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/ShellNotClosedSystemTest.java @@ -43,7 +43,7 @@ public class ShellNotClosedSystemTest { @Test public void testShellNotClosed1() throws CityGmlParseException, IOException, InvalidGmlFileException { 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); assertEquals(ResultStatus.OK, cr.getResultStatus()); } @@ -51,7 +51,7 @@ public class ShellNotClosedSystemTest { @Test public void testShellNotClosed2() throws CityGmlParseException, IOException, InvalidGmlFileException { 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); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ErrorId.GE_S_NOT_CLOSED, cr.getError().getErrorId()); diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TestUtil.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TestUtil.java index f1dd8d201d058926dd928d853bb6ebd597ed94aa..48e82e8da7de8706294bfe7d1a34c7d14c7ddb5a 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TestUtil.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TestUtil.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import de.hft.stuttgart.citydoctor2.check.Checker; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; @@ -89,15 +90,16 @@ public class TestUtil { if (gmlId == null) { return null; } - Polygon result = getPolygonById(gmlId, model.getBuildings()); + Polygon result = getPolygonById(gmlId, model.getBuildings().toList()); + if (result != null) { return result; } - result = getPolygonById(gmlId, model.getVegetation()); + result = getPolygonById(gmlId, model.getVegetation().toList()); if (result != null) { return result; } - return getPolygonById(gmlId, model.getTransportation()); + return getPolygonById(gmlId, model.getTransportation().toList()); } private static Polygon getPolygonById(String gmlId, List features) { @@ -136,22 +138,17 @@ public class TestUtil { if (featureId == null) { return null; } - for (CityObject co : model.getBuildings()) { - if (featureId.equals(co.getGmlId().getGmlString())) { - return co; - } + Optional result = null; + result = model.getBuildings().filter(b -> featureId.equals(b.getGmlId().toString())).findFirst(); + if (result.isPresent()){ + return result.get(); } - for (CityObject co : model.getTransportation()) { - if (featureId.equals(co.getGmlId().getGmlString())) { - return co; - } + result = model.getTransportation().filter(t-> featureId.equals(t.getGmlId().toString())).findFirst(); + if (result.isPresent()){ + return result.get(); } - for (CityObject co : model.getVegetation()) { - if (featureId.equals(co.getGmlId().getGmlString())) { - return co; - } - } - return null; - } + result = model.getVegetation().filter(t-> featureId.equals(t.getGmlId().toString())).findFirst(); + return result.orElse(null); + } } diff --git a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TooFewPolygonsSystemTest.java b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TooFewPolygonsSystemTest.java index 4cf0caa6bbcaf7691a942e00a674f678f9c19ca9..0bf43727b8b99291d8df8a2d6c16e25f758fa486 100644 --- a/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TooFewPolygonsSystemTest.java +++ b/CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/systemtest/TooFewPolygonsSystemTest.java @@ -43,7 +43,7 @@ public class TooFewPolygonsSystemTest { @Test public void testTooFewPolygons1() throws CityGmlParseException, IOException, InvalidGmlFileException { 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); assertEquals(ResultStatus.OK, cr.getResultStatus()); } @@ -51,7 +51,7 @@ public class TooFewPolygonsSystemTest { @Test public void testTooFewPolygons2() throws CityGmlParseException, IOException, InvalidGmlFileException { 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); assertEquals(ResultStatus.ERROR, cr.getResultStatus()); assertEquals(ErrorId.GE_S_TOO_FEW_POLYGONS, cr.getError().getErrorId()); diff --git a/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml b/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml index 52eb30300a1e7c9c0e4598c22aad858328aedfee..ec1f300cee9974e688d6e4f4f7c4f9b11953cd7a 100644 --- a/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml +++ b/CityDoctorParent/Extensions/CityDoctorAutoPro/pom.xml @@ -6,7 +6,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 ../../pom.xml CityDoctorAutoPro diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml b/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml index 2b07c026a5b412210ccdb584563acf42de815420..01e74c250d42360399c1b8c6ba2c73ee5ed30856 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml +++ b/CityDoctorParent/Extensions/CityDoctorGUI/pom.xml @@ -6,7 +6,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 ../../pom.xml CityDoctorGUI diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java index 23ae6271bcbd5cd62f8fde072e25fd3ad19ac852..fdfd46aa8bd4cf48fccf75346bf64936d7bd1a9d 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CheckDialog.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import de.hft.stuttgart.citydoctor2.parser.ProgressListener; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.control.Alert; @@ -139,8 +140,6 @@ public class CheckDialog { @FXML private Label schematronFileLabel; - @FXML - private VBox zipArchiveOptionsVBox; @FXML private CheckBox streamCheckOption; @FXML @@ -161,7 +160,6 @@ public class CheckDialog { private CityDoctorController controller; private FilterPane filterPane; private MainWindow window; - private boolean zipArchiveMode; public CheckDialog(MainWindow window, Window parent, CityDoctorController controller) throws IOException { this.window = window; @@ -181,7 +179,6 @@ public class CheckDialog { } public void initialize() { - setupZipArchiveOptions(); createEnableColumn(geometricTable); createNameColumn(geometricTable); @@ -286,46 +283,6 @@ public class CheckDialog { }); } - private void setupZipArchiveOptions() { - streamCheckOption.selectedProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue 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() { selectBtn.setOnAction(ae -> { @@ -494,25 +451,13 @@ public class CheckDialog { String startingChecks = Localization.getText("CheckDialog.startingChecks"); logger.info(startingChecks); } - if (zipArchiveMode) { - Path outputPath = null; - if (streamCheckOption.isSelected()) { - if (outputPathTextField.getText().isEmpty()) { - 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)); + ProgressListener l = new ProgressListener() { + @Override + public void updateProgress(float state) { + Platform.runLater(() -> progress.setProgress(state)); } - controller.startZipFileChecks(config, progress::setProgress, streamCheckOption.isSelected(), - outputPath, pdfReportsOption.isSelected(), - xmlReportsOption.isSelected()); - } else { - controller.startChecks(config, progress::setProgress); - } + }; + controller.startChecks(config, l); if (logger.isInfoEnabled()) { String checksDone = Localization.getText("CheckDialog.checksDone"); diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java index cda811c74f0c500ab9e4a6c184e76d99b8779fd7..3d68b2fc379bdc485c302cccebcafe16ae69f9b1 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java @@ -5,6 +5,7 @@ import de.hft.stuttgart.citydoctor2.check.Checker; import de.hft.stuttgart.citydoctor2.check.ErrorId; import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; 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.exceptions.CityDoctorWriteException; import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat; @@ -16,16 +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.mapper.citygml3.GMLValidationHandler; 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.zip.CityGmlZipArchive; -import de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry; -import de.hft.stuttgart.citydoctor2.zip.MalformedZipFileException; import de.hft.stuttgart.quality.adapter.types.ErrorAdapter; import javafx.application.Platform; import javafx.scene.chart.XYChart.Data; import javafx.scene.chart.XYChart.Series; -import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; import javafx.scene.control.TreeItem; @@ -33,22 +29,18 @@ import javafx.scene.control.TreeView; import javafx.scene.paint.Color; import javafx.stage.FileChooser; 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.Logger; import org.citygml4j.core.model.core.CityModel; import org.xml.sax.SAXParseException; -import java.awt.*; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.*; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; public class CityDoctorController { @@ -61,9 +53,7 @@ public class CityDoctorController { private CityDoctorModel model; private ParserConfiguration currentConfig; private String sourceFile; - private CityGmlZipArchive zipArchive; - private ZipEntryManager currentZipEntryManager; - private HashMap previousCheckers = null; + private Checker currentChecker; private HighlightController highlightController; @@ -78,7 +68,9 @@ public class CityDoctorController { private AtomicInteger waterChunkNr = new AtomicInteger(0); private AtomicInteger landChunkNr = 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) { this.mainWindow = mainWindow; @@ -96,7 +88,7 @@ public class CityDoctorController { try { Platform.runLater(() -> { mainWindow.getOpenBtn().setDisable(true); - mainWindow.getZipManagerBtn().setDisable(true); + mainWindow.getWriteReportButton().setDisable(true); mainWindow.getMeshGroup().getChildren().clear(); @@ -104,12 +96,6 @@ public class CityDoctorController { mainWindow.resetSearchBar(); mainWindow.resetFilterComboBox(); }); - if (path.endsWith(".zip")) { - loadCityGmlZipFile(path, numberOfRoundingPlaces, useValidation, lowMemory); - return; - } - currentZipEntryManager = null; - previousCheckers = null; currentChecker = null; currentConfig = new ParserConfiguration(numberOfRoundingPlaces, useValidation, lowMemory); GMLValidationHandler handler = null; @@ -136,7 +122,7 @@ public class CityDoctorController { } }; } - model = CityGmlParser.parseCityGmlFile(path, currentConfig, l, handler, true); + model = CityGmlParser.parseCityGmlFile(path, currentConfig, l, handler); if (!validationIssues.isEmpty()) { StringJoiner sj = new StringJoiner("\n"); validationIssues.stream().forEach(sj::add); @@ -156,7 +142,6 @@ public class CityDoctorController { mainWindow.getSaveBtn().setDisable(false); mainWindow.getResetCameraBtn().setDisable(false); mainWindow.getHideRoofBtn().setDisable(false); - mainWindow.getZipManagerBtn().setDisable(true); mainWindow.getNorthArrow().setVisible(true); mainWindow.alignNorthArrow(); setupFeatureTabs(); @@ -167,109 +152,20 @@ public class CityDoctorController { } } - 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.alignNorthArrow(); - setupFeatureTabs(); - buildTrees(); - updateFeatureTrees(); - mainWindow.getWriteReportButton().setDisable(currentChecker == null); - }); - } finally { - Platform.runLater(() -> mainWindow.getOpenBtn().setDisable(false)); - } - - } - - public void showZipManager() { - Platform.runLater(() -> currentZipEntryManager.show()); + public static int getMaxFeaturesPerChunk(){ + return MAX_FEATURES_PER_CHUNK; } private void setupFeatureTabs() { - mainWindow.setDisableOfFeatureTab(FeatureType.BUILDING, model.getBuildings().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.VEGETATION, model.getVegetation().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.TRANSPORTATION, model.getTransportation().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.TUNNEL, model.getTunnels().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.BRIDGE, model.getBridges().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.WATER, model.getWater().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.LAND, model.getLand().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.CITY_FURNITURE, model.getCityFurniture().isEmpty()); - mainWindow.setDisableOfFeatureTab(FeatureType.GENERIC_CITY_OBJECT, model.getGenericCityObjects().isEmpty()); + mainWindow.setDisableOfFeatureTab(FeatureType.BUILDING, model.getBuildingCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.VEGETATION, model.getVegetationCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.TRANSPORTATION, model.getTransportationCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.TUNNEL, model.getTunnelCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.BRIDGE, model.getBridgeCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.WATER, model.getWaterCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.LAND, model.getLandCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.CITY_FURNITURE, model.getCityFurnitureCount() == 0); + mainWindow.setDisableOfFeatureTab(FeatureType.OTHER_CITY_OBJECT, model.getOtherCityObjectsCount() == 0); } public void buildTrees() { @@ -282,7 +178,7 @@ public class CityDoctorController { buildWater(model); buildLand(model); buildCityFurniture(model); - buildOtherCityObjects(model); + buildGenericCityObjects(model); buildTunnel(model); } @@ -295,126 +191,134 @@ public class CityDoctorController { waterChunkNr.set(0); landChunkNr.set(0); cityFurnitureChunkNr.set(0); - genericCityObjectsChunkNr.set(0); + otherCityObjectsChunkNr.set(0); } private void buildLand(CityDoctorModel model) { - if (model.getLand().isEmpty()) { + if (model.getLandCount() == 0) { return; } TreeView landView = mainWindow.getTerrainView(); - TreeItem landRoot = new TreeItem<>(new CityObjectGroupNode(model.getLand(), "Land", + TreeItem landRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Land", Color.BROWN)); landRoot.setExpanded(true); landView.setRoot(landRoot); - buildLandFromList(model.getLand(), landView.getRoot()); - addMoreButtonIfNecessary(model.getLand(), landView, landRoot, landChunkNr); + Supplier> supply = model::getLand; + buildLandTreeFromList(supply, landView.getRoot()); + addMoreButtonForLand(landView, landRoot, landChunkNr, supply, model.getLandCount()); } - private void buildLandFromList(List list, TreeItem root) { + private void buildLandTreeFromList(Supplier> supply, TreeItem root) { int landChunk = landChunkNr.get(); - for (int i = landChunk * MAX_FEATURES_PER_CHUNK; i < (landChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - CityObject land = list.get(i); + supply.get().skip((long) landChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(land ->{ CityObjectNode node = new CityObjectNode(land); TreeItem item = new TreeItem<>(node); item.setExpanded(true); root.getChildren().add(item); createGeometryNodes(land, item); - - } + }); } private void buildCityFurniture(CityDoctorModel model) { - if (model.getCityFurniture().isEmpty()) { + if (model.getCityFurnitureCount() == 0) { return; } TreeView cityFurnitureView = mainWindow.getCityFurnitureView(); - TreeItem cityFurnitureRoot = new TreeItem<>(new CityObjectGroupNode(model.getCityFurniture(), + TreeItem cityFurnitureRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "City Furniture", Color.BLUEVIOLET)); cityFurnitureRoot.setExpanded(true); cityFurnitureView.setRoot(cityFurnitureRoot); - buildCityFurnitureTreeFromList(model.getCityFurniture(), cityFurnitureView.getRoot()); - addMoreButtonIfNecessary(model.getCityFurniture(), cityFurnitureView, cityFurnitureRoot, cityFurnitureChunkNr); + Supplier> supply = model::getCityFurniture; + buildCityFurnitureTreeFromList(supply, cityFurnitureView.getRoot()); + addMoreButtonForCityFurniture(cityFurnitureView, cityFurnitureRoot, cityFurnitureChunkNr, supply, + model.getCityFurnitureCount()); } - private void buildOtherCityObjects(CityDoctorModel model) { - if (model.getGenericCityObjects().isEmpty()) { + private void buildGenericCityObjects(CityDoctorModel model) { + if (model.getOtherCityObjectsCount() == 0) { return; } - TreeView otherObjectsView = mainWindow.getGenericCityObjectView(); - TreeItem otherObjectsRoot = new TreeItem<>(new CityObjectGroupNode(model.getGenericCityObjects(), + TreeView otherObjectsView = mainWindow.getOtherCityObjectView(); + TreeItem otherObjectsRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Generic CityObjects", Color.DARKGRAY)); otherObjectsRoot.setExpanded(true); otherObjectsView.setRoot(otherObjectsRoot); - buildGenericCityObjectTreeFromList(model.getGenericCityObjects(), otherObjectsView.getRoot()); - addMoreButtonIfNecessary(model.getGenericCityObjects(), otherObjectsView, otherObjectsRoot, genericCityObjectsChunkNr); + Supplier> supply = model::getOtherCityObjects; + buildOtherCityObjectsTreeFromList(supply, otherObjectsView.getRoot()); + addMoreButtonForOtherCityObjects( otherObjectsView, otherObjectsRoot, otherCityObjectsChunkNr, supply, + model.getOtherCityObjectsCount()); } private void buildWater(CityDoctorModel model) { - if (model.getWater().isEmpty()) { + if (model.getWaterCount() == 0) { return; } TreeView waterView = mainWindow.getWaterView(); - TreeItem waterRoot = new TreeItem<>(new CityObjectGroupNode(model.getWater(), "Water", + TreeItem waterRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Water", Color.LIGHTSKYBLUE)); waterRoot.setExpanded(true); waterView.setRoot(waterRoot); - buildWaterTreeFromList(model.getWater(), waterRoot); - addMoreButtonIfNecessary(model.getWater(), waterView, waterRoot, waterChunkNr); + Supplier> supply = model::getWater; + buildWaterTreeFromList(supply, waterRoot); + addMoreButtonForWater(waterView, waterRoot, waterChunkNr, supply, model.getWaterCount()); } private void buildBridges(CityDoctorModel model) { - if (model.getBridges().isEmpty()) { + if (model.getBridgeCount() == 0) { return; } TreeView bridgeView = mainWindow.getBridgeView(); - TreeItem bridgeRoot = new TreeItem<>(new CityObjectGroupNode(model.getBridges(), "Bridges", + TreeItem bridgeRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Bridges", Color.CORAL)); bridgeRoot.setExpanded(true); bridgeView.setRoot(bridgeRoot); - buildBridgeTreeFromList(model.getBridges(), bridgeView.getRoot()); - addMoreButtonIfNecessary(model.getBridges(), bridgeView, bridgeRoot, bridgeChunkNr); + Supplier> supply = model::getBridges; + buildBridgeTreeFromList(supply, bridgeView.getRoot()); + addMoreButtonForBridges(bridgeView, bridgeRoot, bridgeChunkNr, supply, model.getBridgeCount()); } private void buildTransportation(CityDoctorModel model) { - if (model.getTransportation().isEmpty()) { + if (model.getTransportationCount() == 0) { return; } TreeView transView = mainWindow.getTransportationView(); - TreeItem transRoot = new TreeItem<>(new CityObjectGroupNode(model.getTransportation(), + TreeItem transRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Transportation", Color.YELLOW)); transRoot.setExpanded(true); transView.setRoot(transRoot); - buildTransportationTreeFromList(model.getTransportation(), transView.getRoot()); - addMoreButtonIfNecessary(model.getTransportation(), transView, transRoot, transportationChunkNr); + Supplier> supply = model::getTransportation; + buildTransportationTreeFromList(supply, transView.getRoot()); + addMoreButtonForTransportation(transView, transRoot, transportationChunkNr, supply, + model.getTransportationCount()); } private void buildTunnel(CityDoctorModel model) { - if (model.getTunnels().isEmpty()) { + if (model.getTunnelCount() == 0) { return; } TreeView tunnelView = mainWindow.getTunnelView(); - TreeItem tunnelRoot = new TreeItem<>(new CityObjectGroupNode(model.getTunnels(), "Tunnel", + TreeItem tunnelRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Tunnel", Color.SLATEGRAY)); tunnelRoot.setExpanded(true); tunnelView.setRoot(tunnelRoot); - buildTunnelTreeFromList(model.getTunnels(), tunnelRoot); - addMoreButtonIfNecessary(model.getTunnels(), tunnelView, tunnelRoot, tunnelChunkNr); + Supplier> supply = model::getTunnels; + buildTunnelTreeFromList(supply, tunnelRoot); + addMoreButtonForTunnel(tunnelView, tunnelRoot, tunnelChunkNr, supply, model.getTunnelCount()); } private void buildVegetation(CityDoctorModel model) { - if (model.getVegetation().isEmpty()) { + if (model.getVegetationCount() == 0) { return; } TreeView vegetationsView = mainWindow.getVegetationView(); - TreeItem vegRoot = new TreeItem<>(new CityObjectGroupNode(model.getVegetation(), + TreeItem vegRoot = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Vegetation", Color.LIGHTGREEN)); vegRoot.setExpanded(true); vegetationsView.setRoot(vegRoot); - buildVegetationTreeFromList(model.getVegetation(), vegRoot); - addMoreButtonIfNecessary(model.getVegetation(), vegetationsView, vegRoot, vegetationChunkNr); + Supplier> supply = model::getVegetation; + buildVegetationTreeFromList(supply, vegRoot); + addMoreButtonForVegetation(vegetationsView, vegRoot, vegetationChunkNr, supply, model.getVegetationCount()); } private void addMoreButtonIfNecessary(List list, TreeView view, @@ -430,7 +334,7 @@ public class CityDoctorController { chunkCounter.incrementAndGet(); int visibleFeatures = countVisibleNodes(view); - buildTreeFromList(list, root, chunkCounter); +// buildTreeFromList(list, root, chunkCounter); updateTree(root); if (selectedIndex >= 0) { view.getSelectionModel().select(selectedIndex); @@ -446,17 +350,34 @@ public class CityDoctorController { } } + private void moreButton(CityDoctorModel model, TreeView view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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) { - if (model.getBuildings().isEmpty()) { + if (model.getBuildingCount() == 0) { return; } TreeView buildingsView = mainWindow.getBuildingsView(); - TreeItem root = new TreeItem<>(new CityObjectGroupNode(model.getBuildings(), "Buildings", + TreeItem root = new TreeItem<>(new CityObjectGroupNode(Collections.emptyList(), "Buildings", Color.WHITE)); root.setExpanded(true); buildingsView.setRoot(root); - buildBuildingTreeFromList(model.getBuildings(), root); - addMoreButtonToBuildingsIfNecessary(model.getBuildings(), buildingsView, root, buildingChunkNr); + Supplier> supply = model::getBuildings; + buildBuildingTreeFromList(supply, root); + addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, supply, model.getBuildingCount()); } @@ -472,7 +393,7 @@ public class CityDoctorController { root.getChildren().remove(root.getChildren().size() - 1); chunkCounter.getAndIncrement(); int visibleFeatures = countVisibleNodes(view); - buildBuildingTreeFromList(list, root); +// buildBuildingTreeFromList(list, root); updateTree(root); if (selectedIndex >= 0) { view.getSelectionModel().select(selectedIndex); @@ -488,6 +409,141 @@ public class CityDoctorController { } } + private void addMoreButtonForBuildings(TreeView view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view, TreeItem root, + AtomicInteger chunkCounter, Supplier> 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 view) { return countVisibleNodes(view.getRoot()) + 1; } @@ -502,17 +558,16 @@ public class CityDoctorController { return visibleFeatures; } - private void buildTreeFromList(List cos, TreeItem root, + private void buildTreeFromList(Supplier> supply, TreeItem root, AtomicInteger chunkCounter) { - int chunk = chunkCounter.get(); - for (int i = chunk * MAX_FEATURES_PER_CHUNK; i < (chunk + 1) * MAX_FEATURES_PER_CHUNK && i < cos.size(); i++) { - CityObject co = cos.get(i); + int buildingChunk = buildingChunkNr.get(); + supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(co ->{ CityObjectNode node = new CityObjectNode(co); TreeItem nodeItem = new TreeItem<>(node); nodeItem.setExpanded(true); root.getChildren().add(nodeItem); createGeometryNodes(co, nodeItem); - } + }); } private void buildTreeFromListWithProducer(List cos, TreeItem root, @@ -536,7 +591,7 @@ public class CityDoctorController { mainWindow.getWaterView().setRoot(null); mainWindow.getTerrainView().setRoot(null); mainWindow.getCityFurnitureView().setRoot(null); - mainWindow.getGenericCityObjectView().setRoot(null); + mainWindow.getOtherCityObjectView().setRoot(null); mainWindow.getErrorTree().getRoot().getChildren().clear(); mainWindow.getAttributeView().getRoot().getChildren().clear(); mainWindow.getGlobalErrorsView().getItems().clear(); @@ -583,11 +638,9 @@ public class CityDoctorController { return nodeItem; } - private void buildBuildingTreeFromList(List list, TreeItem root) { + private void buildBuildingTreeFromList(Supplier> supply, TreeItem root) { int buildingChunk = buildingChunkNr.get(); - for (int i = buildingChunk * MAX_FEATURES_PER_CHUNK; i < (buildingChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - Building b = list.get(i); + supply.get().skip((long) buildingChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(b ->{ TreeItem item = buildTopLevelCityObjectNode(b, root, b.getBoundarySurfaces()); createBuildingInstallationNodes(b, item); @@ -597,14 +650,12 @@ public class CityDoctorController { createBuildingStoreyNodes(b, item); createBuildingUnitNodes(b, item); createBuildingPartNodes(b, item); - } + }); } - private void buildBridgeTreeFromList(List list, TreeItem root) { + private void buildBridgeTreeFromList(Supplier> supply, TreeItem root) { int bridgeChunk = bridgeChunkNr.get(); - for (int i = bridgeChunk * MAX_FEATURES_PER_CHUNK; i < (bridgeChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - BridgeObject bridge = list.get(i); + supply.get().skip((long) bridgeChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(bridge ->{ TreeItem item = buildTopLevelCityObjectNode(bridge, root, bridge.getBoundarySurfaces()); createBridgeRoomNodes(bridge, item); @@ -612,55 +663,46 @@ public class CityDoctorController { createBridgeFurnitureNodes(bridge, item); createBridgeConstructiveElementsNodes(bridge, item); createBridgePartNodes(bridge, item); - } + }); } - private void buildTransportationTreeFromList(List list, TreeItem root) { + private void buildTransportationTreeFromList(Supplier> supply, TreeItem root) { int transportChunk = transportationChunkNr.get(); - for (int i = transportChunk * MAX_FEATURES_PER_CHUNK; i < (transportChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - TransportationObject t = list.get(i); - TreeItem item = buildTopLevelCityObjectNode(t, root); - createTransportSectionNodes(t, item); - createTrafficSpacesNodes(t, item); - } + supply.get().skip((long) transportChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(trans ->{ + TreeItem item = buildTopLevelCityObjectNode(trans, root); + createTransportSectionNodes(trans, item); + createTrafficSpacesNodes(trans, item); + }); } - private void buildVegetationTreeFromList(List list, TreeItem root) { + private void buildVegetationTreeFromList(Supplier> supply, TreeItem root) { int vegetationChunk = vegetationChunkNr.get(); - for (int i = vegetationChunk * MAX_FEATURES_PER_CHUNK; i < (vegetationChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - Vegetation v = list.get(i); - buildTopLevelCityObjectNode(v, root); - } + supply.get().skip((long) vegetationChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(veg ->{ + buildTopLevelCityObjectNode(veg, root); + }); + } - private void buildWaterTreeFromList(List list, TreeItem root) { + private void buildWaterTreeFromList(Supplier> supply, TreeItem root) { int waterChunk = waterChunkNr.get(); - for (int i = waterChunk * MAX_FEATURES_PER_CHUNK; i < (waterChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - WaterObject w = list.get(i); - buildTopLevelCityObjectNode(w, root); - } + supply.get().skip((long) waterChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(wat ->{ + buildTopLevelCityObjectNode(wat, root); + }); } - private void buildCityFurnitureTreeFromList(List list, TreeItem root) { + private void buildCityFurnitureTreeFromList(Supplier> supply, TreeItem root) { int cityFurnChunk = cityFurnitureChunkNr.get(); - for (int i = cityFurnChunk * MAX_FEATURES_PER_CHUNK; i < (cityFurnChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - CityFurniture cf = list.get(i); + supply.get().skip((long) cityFurnChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(cf ->{ buildTopLevelCityObjectNode(cf, root); - } + }); } - private void buildGenericCityObjectTreeFromList(List list, TreeItem root) { - int genericObjectChunk = genericCityObjectsChunkNr.get(); - for (int i = genericObjectChunk * MAX_FEATURES_PER_CHUNK; i < (genericObjectChunk + 1) * MAX_FEATURES_PER_CHUNK - && i < list.size(); i++) { - GenericCityObject goc = list.get(i); - buildTopLevelCityObjectNode(goc, root); - } + private void buildOtherCityObjectsTreeFromList(Supplier> supply, TreeItem root) { + int genericObjectChunk = otherCityObjectsChunkNr.get(); + supply.get().skip((long) genericObjectChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(gen ->{ + buildTopLevelCityObjectNode(gen, root); + }); } private void createTransportSectionNodes(TransportationObject t, TreeItem root) { @@ -734,10 +776,9 @@ public class CityDoctorController { } - private void buildTunnelTreeFromList(List list, TreeItem root) { + private void buildTunnelTreeFromList(Supplier> supply, TreeItem root) { int tunnelChunk = tunnelChunkNr.get(); - for (int i = tunnelChunk * MAX_FEATURES_PER_CHUNK; i < (tunnelChunk + 1) * MAX_FEATURES_PER_CHUNK && i < list.size(); i++) { - Tunnel tunnel = list.get(i); + supply.get().skip((long) tunnelChunk * MAX_FEATURES_PER_CHUNK).limit(MAX_FEATURES_PER_CHUNK).forEach(tunnel ->{ TreeItem item = buildTopLevelCityObjectNode(tunnel, root); createTunnelHollowNodes(tunnel, item); @@ -745,7 +786,8 @@ public class CityDoctorController { createTunnelFurnitureNodes(tunnel, item); createTunnelConstructiveElementsNodes(tunnel, item); createTunnelPartNodes(tunnel, item); - } + }); + } private void createTunnelInstallationNodes(Tunnel tunnel, TreeItem root) { @@ -1036,13 +1078,11 @@ public class CityDoctorController { config.setNumberOfRoundingPlacesInGlobalParameters(currentConfig.getNumberOfRoundingPlaces()); config.setParserConfig(currentConfig); currentChecker = new Checker(config, model); - if (previousCheckers != null) { - previousCheckers.put(model, currentChecker); - } currentChecker.runChecks(l); Platform.runLater(() -> { // apply check results to tree views + buildTrees(); updateFeatureTrees(); updateTree(mainWindow.getPolygonsView().getRoot()); updateGlobalErrors(); @@ -1054,137 +1094,10 @@ public class CityDoctorController { } } - private void updateGlobalErrors() { - GlobalErrorVisitor globErrVisitor = new GlobalErrorVisitor(mainWindow); - for (CheckError e : model.getGlobalErrors()) { - e.accept(globErrVisitor); - } - } - - public void startZipFileChecks(ValidationConfiguration config, ProgressListener l, boolean lowMemoryMode, - Path outputPath, boolean pdfReports, boolean xmlReports) { - if (zipArchive == null && logger.isWarnEnabled()) { - logger.warn(Localization.getText("CityDoctorController.noZipFile")); - } - - 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()); - updateGlobalErrors(); - 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); - } + private void updateGlobalErrors() { + GlobalErrorVisitor globErrVisitor = new GlobalErrorVisitor(mainWindow); + for (CheckError e : model.getGlobalErrors()) { + e.accept(globErrVisitor); } } @@ -1196,7 +1109,7 @@ public class CityDoctorController { updateTree(mainWindow.getCityFurnitureView().getRoot()); updateTree(mainWindow.getTransportationView().getRoot()); updateTree(mainWindow.getWaterView().getRoot()); - updateTree(mainWindow.getGenericCityObjectView().getRoot()); + updateTree(mainWindow.getOtherCityObjectView().getRoot()); updateTree(mainWindow.getTunnelView().getRoot()); renderer.updateErrors(); } @@ -1236,15 +1149,13 @@ public class CityDoctorController { private Map getErrorStats() { Map stats = new HashMap<>(); - addErrorStats(stats, model.getBridges()); - addErrorStats(stats, model.getBuildings()); - addErrorStats(stats, model.getLand()); - addErrorStats(stats, model.getTunnels()); - addErrorStats(stats, model.getTransportation()); - addErrorStats(stats, model.getVegetation()); - addErrorStats(stats, model.getWater()); - addErrorStats(stats, model.getCityFurniture()); - addErrorStats(stats, model.getGenericCityObjects()); + List errors = new ArrayList<>(); + model.createFeatureStream().forEach(co -> co.collectContainedErrors(errors)); + Set filteredErrors = new HashSet<>(errors); + for (CheckError error : filteredErrors) { + ErrorStat stat = stats.computeIfAbsent(error.getErrorId(), ErrorStat::new); + stat.incrementCount(); + } return stats; } @@ -1258,13 +1169,15 @@ public class CityDoctorController { ErrorStat stat = stats.computeIfAbsent(error.getErrorId(), ErrorStat::new); stat.incrementCount(); } + + } public void export(CityObject co) { if (model == null) { return; } - CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile()); + CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile(), new UnconnectedCache()); newModel.setCityModel(new CityModel()); newModel.addCityObject(co); newModel.setParsedCityGMLVersion(model.getCityGMLVersion()); @@ -1319,96 +1232,113 @@ public class CityDoctorController { case WATER -> filterWaterTree(searchString); case LAND -> filterLandTree(searchString); case CITY_FURNITURE -> filterCityFurnitureTree(searchString); - case GENERIC_CITY_OBJECT -> filterGenericCityObjectTree(searchString); + case OTHER_CITY_OBJECT -> filterOtherCityObjectsTree(searchString); } } private void filterBuildingTree(String searchString) { - List foundBuildings = filterFeatures(searchString, model.getBuildings()); + Supplier> foundBuildings = () -> model.getBuildings(). + filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundBuildings.get().count(); TreeView buildingsView = mainWindow.getBuildingsView(); TreeItem root = buildingsView.getRoot(); root.getChildren().clear(); buildBuildingTreeFromList(foundBuildings, root); updateTree(root); - addMoreButtonToBuildingsIfNecessary(foundBuildings, buildingsView, root, buildingChunkNr); + addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, foundBuildings, featureCount); } private void filterBridgeTree(String searchString) { - List foundBridges = filterFeatures(searchString, model.getBridges()); + Supplier> foundBridges = () -> model.getBridges(). + filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundBridges.get().count(); TreeView bridgeView = mainWindow.getBridgeView(); TreeItem root = bridgeView.getRoot(); root.getChildren().clear(); buildBridgeTreeFromList(foundBridges, root); updateTree(root); - addMoreButtonIfNecessary(foundBridges, bridgeView, root, bridgeChunkNr); + addMoreButtonForBridges(bridgeView, root, bridgeChunkNr, foundBridges, featureCount); } private void filterTunnelTree(String searchString) { - List foundTunnel = filterFeatures(searchString, model.getTunnels()); + Supplier> foundTunnel = () -> model.getTunnels().filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundTunnel.get().count(); TreeView tunnelView = mainWindow.getTunnelView(); TreeItem root = tunnelView.getRoot(); root.getChildren().clear(); buildTunnelTreeFromList(foundTunnel, root); updateTree(root); - addMoreButtonIfNecessary(foundTunnel, tunnelView, root, tunnelChunkNr); + addMoreButtonForTunnel(tunnelView, root, tunnelChunkNr, foundTunnel, featureCount); } private void filterVegetationTree(String searchString) { - List foundVegetation = filterFeatures(searchString, model.getVegetation()); + Supplier> foundVegetation = () -> model.getVegetation(). + filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundVegetation.get().count(); TreeView vegetationView = mainWindow.getVegetationView(); TreeItem root = vegetationView.getRoot(); root.getChildren().clear(); buildVegetationTreeFromList(foundVegetation, root); updateTree(root); - addMoreButtonIfNecessary(foundVegetation, vegetationView, root, vegetationChunkNr); + addMoreButtonForVegetation(vegetationView, root, vegetationChunkNr, foundVegetation, featureCount); } private void filterTransportationTree(String searchString) { - List foundTransportation = filterFeatures(searchString, model.getTransportation()); + Supplier> foundTransportation = () -> model.getTransportation(). + filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundTransportation.get().count(); TreeView transportationView = mainWindow.getTransportationView(); TreeItem root = transportationView.getRoot(); root.getChildren().clear(); buildTransportationTreeFromList(foundTransportation, root); updateTree(root); - addMoreButtonIfNecessary(foundTransportation, transportationView, root, transportationChunkNr); + addMoreButtonForTransportation(transportationView, root, transportationChunkNr, + foundTransportation, featureCount); } private void filterWaterTree(String searchString) { - List foundWater = filterFeatures(searchString, model.getWater()); + Supplier> foundWater = () -> model.getWater().filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundWater.get().count(); TreeView waterView = mainWindow.getWaterView(); TreeItem root = waterView.getRoot(); root.getChildren().clear(); buildWaterTreeFromList(foundWater, root); - addMoreButtonIfNecessary(foundWater, waterView, root, waterChunkNr); + addMoreButtonForWater(waterView, root, waterChunkNr, foundWater, featureCount); } private void filterLandTree(String searchString) { - List foundLand = filterFeatures(searchString, model.getLand()); + Supplier> foundLand = () -> model.getLand().filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundLand.get().count(); TreeView landView = mainWindow.getTerrainView(); TreeItem root = landView.getRoot(); root.getChildren().clear(); - buildLandFromList(foundLand, root); - addMoreButtonIfNecessary(foundLand, landView, root, landChunkNr); + buildLandTreeFromList(foundLand, root); + addMoreButtonForLand(landView, root, landChunkNr, foundLand, featureCount); } private void filterCityFurnitureTree(String searchString) { - List foundCityFurniture = filterFeatures(searchString, model.getCityFurniture()); + Supplier> foundCityFurniture = () -> model.getCityFurniture(). + filter(co -> featureFilter(co, searchString)); + int featureCount = (int) foundCityFurniture.get().count(); TreeView cityFurnitureView = mainWindow.getCityFurnitureView(); TreeItem root = cityFurnitureView.getRoot(); root.getChildren().clear(); buildCityFurnitureTreeFromList(foundCityFurniture, root); - addMoreButtonIfNecessary(foundCityFurniture, cityFurnitureView, root, cityFurnitureChunkNr); + addMoreButtonForCityFurniture(cityFurnitureView, root, cityFurnitureChunkNr, foundCityFurniture, featureCount); } - private void filterGenericCityObjectTree(String searchString) { - List foundGenericCityObject = filterFeatures(searchString, model.getGenericCityObjects()); - TreeView genericCityObjectView = mainWindow.getGenericCityObjectView(); + private void filterOtherCityObjectsTree(String searchString) { + Supplier> foundGenericCityObject = () -> model.getOtherCityObjects(). + filter(co ->featureFilter(co, searchString)); + int featureCount = (int) foundGenericCityObject.get().count(); + TreeView genericCityObjectView = mainWindow.getOtherCityObjectView(); TreeItem root = genericCityObjectView.getRoot(); root.getChildren().clear(); - buildGenericCityObjectTreeFromList(foundGenericCityObject, root); - addMoreButtonIfNecessary(foundGenericCityObject, genericCityObjectView, root, genericCityObjectsChunkNr); + buildOtherCityObjectsTreeFromList(foundGenericCityObject, root); + addMoreButtonForOtherCityObjects(genericCityObjectView, root, otherCityObjectsChunkNr, + foundGenericCityObject, featureCount); } private List filterFeatures(String searchString, List features) { @@ -1421,6 +1351,10 @@ public class CityDoctorController { return foundFeatures; } + private boolean featureFilter(CityObject co, String searchString) { + return co.getGmlId().getGmlString().contains(searchString); + } + public void resetSearch(FeatureType selectedTab) { if (model == null) { return; @@ -1455,141 +1389,192 @@ public class CityDoctorController { } mainWindow.resetSearchBar(); root.getChildren().clear(); - List errorBuildings = new ArrayList<>(); - for (Building b : model.getBuildings()) { - if (b.containsAnyError()) { - errorBuildings.add(b); - } - } resetFeatureChunks(); - buildBuildingTreeFromList(errorBuildings, root); + List foundBuildings = model.getCache().getErrorFeatureIds(); + List idList = model.getBuildingIds(); + foundBuildings.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundBuildings).map(co -> (Building) co); + buildBuildingTreeFromList(supply, root); updateTree(root); - addMoreButtonToBuildingsIfNecessary(errorBuildings, buildingsView, root, buildingChunkNr); + addMoreButtonForBuildings(buildingsView, root, buildingChunkNr, supply, foundBuildings.size()); } public void fillTreeViewWithErrorVegetation() { + TreeView vegetationView = mainWindow.getVegetationView(); + TreeItem root = vegetationView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getVegetationView(), model.getVegetation(), vegetationChunkNr); + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundVegetation = model.getCache().getErrorFeatureIds(); + List idList = model.getVegetationIds(); + foundVegetation.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundVegetation).map(co -> (Vegetation) co); + buildVegetationTreeFromList(supply, root); + updateTree(root); + addMoreButtonForVegetation(vegetationView, root, vegetationChunkNr, supply, foundVegetation.size()); } public void fillTreeViewWithErrorBridges() { + TreeView bridgeView = mainWindow.getBridgeView(); + TreeItem root = bridgeView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getBridgeView(), model.getBridges(), bridgeChunkNr); + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundBridge = model.getCache().getErrorFeatureIds(); + List idList = model.getBridgeIds(); + foundBridge.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundBridge).map(co -> (BridgeObject) co); + buildBridgeTreeFromList(supply, root); + updateTree(root); + addMoreButtonForBridges(bridgeView, root, bridgeChunkNr, supply, foundBridge.size()); } public void fillTreeViewWithErrorLand() { + TreeView landView = mainWindow.getTerrainView(); + TreeItem root = landView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getTerrainView(), model.getLand(), landChunkNr); + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundLand = model.getCache().getErrorFeatureIds(); + List idList = model.getLandIds(); + foundLand.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundLand).map(co -> (CityObject) co); + buildLandTreeFromList(supply, root); + updateTree(root); + addMoreButtonForLand(landView, root, landChunkNr, supply, foundLand.size()); } public void fillTreeViewWithErrorCityFurniture() { + TreeView cityFurnitureView = mainWindow.getCityFurnitureView(); + TreeItem root = cityFurnitureView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getCityFurnitureView(), - model.getCityFurniture(), cityFurnitureChunkNr); + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundCityFurniture = model.getCache().getErrorFeatureIds(); + List idList = model.getCityFurnitureIds(); + foundCityFurniture.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> 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 genericCityObjectsView = mainWindow.getOtherCityObjectView(); + TreeItem root = genericCityObjectsView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getGenericCityObjectView(), - model.getGenericCityObjects(), genericCityObjectsChunkNr); + if (root == null) { + return; + } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundOtherCityObjects = model.getCache().getErrorFeatureIds(); + List idList = model.getOtherCityObjectsIds(); + foundOtherCityObjects.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundOtherCityObjects).map(co -> (GenericCityObject) co); + buildOtherCityObjectsTreeFromList(supply, root); + updateTree(root); + addMoreButtonForOtherCityObjects(genericCityObjectsView, root, otherCityObjectsChunkNr, supply, foundOtherCityObjects.size()); } public void fillTreeViewWithErrorTransportation() { + TreeView transportationView = mainWindow.getTransportationView(); + TreeItem root = transportationView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getTransportationView(), model.getTransportation(), - transportationChunkNr); - } - - public void fillTreeViewWithErrorTunnel() { - if (model == null) { + if (root == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getTunnelView(), model.getTunnels(), tunnelChunkNr); + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundTransportation = model.getCache().getErrorFeatureIds(); + List idList = model.getTransportationIds(); + foundTransportation.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> 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 tunnelView = mainWindow.getTunnelView(); + TreeItem root = tunnelView.getRoot(); if (model == null) { return; } - fillTreeViewWithErrorCityObjects(mainWindow.getWaterView(), model.getWater(), waterChunkNr); - } - - private void fillTreeViewWithErrorCityObjects(TreeView treeView, List objects, - AtomicInteger chunkCounter) { - TreeItem root = treeView.getRoot(); if (root == null) { return; } mainWindow.resetSearchBar(); root.getChildren().clear(); - List errorObjects = new ArrayList<>(); - for (CityObject co : objects) { - if (co.containsAnyError()) { - errorObjects.add(co); - } - } - buildTreeFromList(errorObjects, root, chunkCounter); + resetFeatureChunks(); + List foundTunnel = model.getCache().getErrorFeatureIds(); + List idList = model.getTunnelIds(); + foundTunnel.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundTunnel).map(co -> (Tunnel) co); + buildTunnelTreeFromList(supply, root); updateTree(root); - addMoreButtonIfNecessary(errorObjects, treeView, root, chunkCounter); + addMoreButtonForTunnel(tunnelView, root, tunnelChunkNr, supply, foundTunnel.size()); + } - public void fillTreeViewFromFeatures(FeatureType selectedTab) { + public void fillTreeViewWithErrorWater() { + TreeView waterView = mainWindow.getWaterView(); + TreeItem root = waterView.getRoot(); if (model == null) { return; } - mainWindow.resetSearchBar(); - switch (selectedTab) { - 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(); + if (root == null) { + return; } + mainWindow.resetSearchBar(); + root.getChildren().clear(); + resetFeatureChunks(); + List foundWater = model.getCache().getErrorFeatureIds(); + List idList = model.getWaterIds(); + foundWater.removeIf(gmlId -> (!idList.contains(gmlId))); + + Supplier> supply = () -> model.getCache().getStream(foundWater).map(co -> (WaterObject) co); + buildWaterTreeFromList(supply, root); + updateTree(root); + addMoreButtonForWater(waterView, root, tunnelChunkNr, supply, foundWater.size()); } public CityDoctorModel getModel() { @@ -1641,7 +1626,7 @@ public class CityDoctorController { public void delete(TreeItem selectedItem) { if (model == null) { 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(); if (render instanceof BuildingNode node) { model.getBuildings().remove(node.getBuilding()); @@ -1654,37 +1639,19 @@ public class CityDoctorController { public void errorFilterIndexChanged(Number newV) { mainWindow.getMeshGroup().getChildren().clear(); mainWindow.unselectEverything(); - if (newV.intValue() == 0) { - fillTreeViewFromFeatures(mainWindow.getSelectedTab()); - } else if (newV.intValue() == 1) { - switch (mainWindow.getSelectedTab()) { - case BUILDING: - fillTreeViewWithErrorBuildings(); - break; - case VEGETATION: - fillTreeViewWithErrorVegetation(); - break; - case BRIDGE: - fillTreeViewWithErrorBridges(); - break; - 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()); - } + if (newV.intValue() == 0) { // Error filter was set to "All" + buildTrees(); + updateFeatureTrees(); + } else if (newV.intValue() == 1) { // Error filter was set to "With errors" + fillTreeViewWithErrorBuildings(); + fillTreeViewWithErrorVegetation(); + fillTreeViewWithErrorBridges(); + fillTreeViewWithErrorLand(); + fillTreeViewWithErrorTransportation(); + fillTreeViewWithErrorTunnel(); + fillTreeViewWithErrorWater(); + fillTreeViewWithErrorCityFurniture(); + fillTreeViewWithErrorOtherCityObjects(); } else { throw new IllegalStateException("Unknown filter index selected: " + newV); } diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java index 78fc80737b913aff0c5a3c462489488ca58d3c3e..3993c617c0e08aec82f750255bf86c18e9c6dc1b 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java @@ -85,12 +85,6 @@ public class MainToolBar { @FXML private ImageView lod4View; - @FXML - private Button zipManagerBtn; - - @FXML - private ImageView zipManagerView; - @FXML private Button aboutBtn; @@ -153,7 +147,6 @@ public class MainToolBar { setupReportButton(); setupResetCameraButton(); setupHideRoofButton(); - setupZipManagerButton(); loadImages(); gridButton.setOnAction(ae -> renderer.showWireFrame(gridButton.isSelected())); @@ -232,10 +225,6 @@ public class MainToolBar { Image img = new Image(inStream); hideRoofView.setImage(img); } - try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/zip.png")) { - Image img = new Image(inStream); - zipManagerView.setImage(img); - } } catch (IOException e) { // ignore close exception } @@ -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() { return checkBtn; } @@ -407,10 +388,6 @@ public class MainToolBar { return resetCameraBtn; } - public Button getZipManagerBtn() { - return zipManagerBtn; - } - public HBox getToolBar() { return toolBar; } diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java index 58810fd551a0c33520250578d8666b0b816ce481..5fb958e150dd53d1dc3f89edef65421a51ab4d26 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java @@ -453,6 +453,7 @@ public class MainWindow extends Application { }); } + @SuppressWarnings("java:S2629") private void checkForStartupLoading() { if (loadFileAtStartup) { logger.info(Localization.getText("MainWindow.loadGivenFile")); @@ -638,7 +639,7 @@ public class MainWindow extends Application { selectedTab = FeatureType.CITY_FURNITURE; break; case 8: - selectedTab = FeatureType.GENERIC_CITY_OBJECT; + selectedTab = FeatureType.OTHER_CITY_OBJECT; break; default: throw new IllegalStateException("Unknown tab index: " + index); @@ -672,7 +673,7 @@ public class MainWindow extends Application { case CITY_FURNITURE: cityFurnitureTab.setDisable(value); break; - case GENERIC_CITY_OBJECT: + case OTHER_CITY_OBJECT: otherObjectsTab.setDisable(value); break; default: @@ -801,10 +802,13 @@ public class MainWindow extends Application { }); 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")); deleteOption.setOnAction(ae -> controller.delete(featureView.getSelectionModel().getSelectedItem())); menu.getItems().add(deleteOption); featureView.setContextMenu(menu); + */ } public void fetchCopyAction(Renderable node) { @@ -1011,7 +1015,7 @@ public class MainWindow extends Application { return attributeView; } - public TreeView getGenericCityObjectView() { + public TreeView getOtherCityObjectView() { return otherObjectsView; } @@ -1157,7 +1161,7 @@ public class MainWindow extends Application { case WATER -> new Pair<>(waterTab, waterView); case LAND -> new Pair<>(terrainTab, terrainView); 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); }; } @@ -1178,13 +1182,6 @@ public class MainWindow extends Application { return mainToolBar.getOpenBtn(); } - public void showZipManager() { - controller.showZipManager(); - } - - public Button getZipManagerBtn() { - return mainToolBar.getZipManagerBtn(); - } public VertexClickHandler getClickHandler() { return clickHandler; diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java index 8e3b6c556dc69007e30d996871032108124c7c0c..d5857b2187938e82b0ff993e95bd687c8e26a48e 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java @@ -120,7 +120,7 @@ public class OpenFileDialog { if (fc == null) { fc = new FileChooser(); 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"), "*.*")); } File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, "")); @@ -153,9 +153,6 @@ public class OpenFileDialog { Thread t = new Thread(() -> { try { - if (path.endsWith(".zip")) { - Platform.runLater(() -> progress.setProgress(-1)); - } controller.loadCityGml(path, numberOfRoundingPlaces, progress::setProgress, useValidation, lowMemory); Platform.runLater(() -> stage.close()); diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java index 9709b35373ee30f37f06bb958ee6a1934286e125..83a556d32f0189588d14008983c994b0d8ec565f 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java @@ -13,6 +13,7 @@ import javafx.scene.paint.PhongMaterial; import javafx.scene.shape.*; import java.util.*; +import java.util.stream.Stream; public class TriangulatedGeometry { @@ -91,15 +92,15 @@ public class TriangulatedGeometry { addPolygonDataFromCityObjects(model.getVegetation(), triGeom, Color.LIGHTGREEN, filters); addPolygonDataFromCityObjects(model.getWater(), triGeom, Color.LIGHTSKYBLUE, filters); addPolygonDataFromCityObjects(model.getCityFurniture(), triGeom, Color.BLUEVIOLET, filters); - addPolygonDataFromCityObjects(model.getGenericCityObjects(), triGeom, Color.BLACK, filters); + addPolygonDataFromCityObjects(model.getOtherCityObjects(), triGeom, Color.BLACK, filters); return triGeom; } - private static void addPolygonDataFromCityObjects(List cos, - TriangulatedGeometry triGeom, Color color, List filters) { + private static void addPolygonDataFromCityObjects(Stream cos, + TriangulatedGeometry triGeom, Color color, List filters) { CityObjectCollector collector = new CityObjectCollector(); cos.forEach(cityObject -> cityObject.accept(collector)); collector.getCityObjects().forEach(cityObject -> addPolygonData(cityObject, triGeom, color, filters)); diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ZipEntryManager.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ZipEntryManager.java deleted file mode 100644 index b27a3f37a5a164cd6271907e671fbe280963a32f..0000000000000000000000000000000000000000 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ZipEntryManager.java +++ /dev/null @@ -1,439 +0,0 @@ -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 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 entryDecompressed = node -> - (node.getEntry().isLoaded() || node.getEntry().getErrorType() != null); - private static final Predicate 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(); - } -} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AddMoreButtonRunnable.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AddMoreButtonRunnable.java new file mode 100644 index 0000000000000000000000000000000000000000..262b309028d56a561bedba099dbc6feaad6e05ae --- /dev/null +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/AddMoreButtonRunnable.java @@ -0,0 +1,68 @@ +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 view; + private final TreeItem root; + private final AtomicInteger chunkCounter; + private static final int MAX_FEATURES_PER_CHUNK = CityDoctorController.getMaxFeaturesPerChunk(); + + + protected AddMoreButtonRunnable(int featureCount, TreeView view, + TreeItem 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 view) { + return countVisibleNodes(view.getRoot()) + 1; + } + + private static int countVisibleNodes(TreeItem root) { + int visibleFeatures = root.getChildren().size(); + for (TreeItem child : root.getChildren()) { + if (!child.getChildren().isEmpty() && child.isExpanded()) { + visibleFeatures += countVisibleNodes(child); + } + } + return visibleFeatures; + } + +} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ZipEntryListCell.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ZipEntryListCell.java deleted file mode 100644 index 745471880256b7eff20a9b6d7e44c0e54c8e297f..0000000000000000000000000000000000000000 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ZipEntryListCell.java +++ /dev/null @@ -1,22 +0,0 @@ -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 { - - @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()); - } -} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/CityObjectNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/CityObjectNode.java index 170891fe8ce6d6e1d87a63c232300e133bcd8df3..7d3fae37a369ab3d03ba906f7734e42bd11c9406 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/CityObjectNode.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/CityObjectNode.java @@ -12,9 +12,11 @@ public class CityObjectNode extends Renderable { private static final Logger logger = LogManager.getLogger(CityObjectNode.class); private final CityObject co; + private String text; public CityObjectNode(CityObject co) { this.co = co; + this.text = co.getDisplayText(); } @Override @@ -30,7 +32,7 @@ public class CityObjectNode extends Renderable { @Override public String getText() { - return co.getDisplayText(); + return text; } @Override diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/ZipEntryNode.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/ZipEntryNode.java deleted file mode 100644 index f4ba0875daaa35c29e0052f392d29a54b2aeecbc..0000000000000000000000000000000000000000 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/node/ZipEntryNode.java +++ /dev/null @@ -1,43 +0,0 @@ -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; - } - -} diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml index 5261641c5b6ca6e3f143e4d0e754e1802438ea45..e0924a244fe035c2460abb84e1d48a4a7ba8c0d5 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/CheckDialog.fxml @@ -2,7 +2,6 @@ - @@ -52,78 +51,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml index 4cf90fff910acf63b9d70da64a989c2e594d990f..17d20351a150a2394aa96ad0e35cdd21fd9fe9f6 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/de/hft/stuttgart/citydoctor2/gui/MainToolBar.fxml @@ -16,13 +16,7 @@ - - + - + @@ -86,7 +80,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/log4j2.xml b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/log4j2.xml index 52b82fc21d441190f17422840d0be52cdfaf3de2..e2d7657f5300c5534ab487bf3a3e1cc3b7645a18 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/log4j2.xml +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/resources/log4j2.xml @@ -19,5 +19,8 @@ + + + \ No newline at end of file diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/pom.xml b/CityDoctorParent/Extensions/CityDoctorHealer/pom.xml index 1d031a02f9edca6ee6beb9876ef77c4bdcc21f1c..f31ce66ad603025f32918033b6dc47651b9f1ed1 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/pom.xml +++ b/CityDoctorParent/Extensions/CityDoctorHealer/pom.xml @@ -6,7 +6,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 ../../pom.xml CityDoctorHealer diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealAllPolygonsWrongOrientationErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealAllPolygonsWrongOrientationErrorTest.java index 58b52a5f4533588824f6e0e552f356f6da6669af..18146a77cb84ef36988543e8406d43c4f7ee1fdd 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealAllPolygonsWrongOrientationErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealAllPolygonsWrongOrientationErrorTest.java @@ -24,11 +24,11 @@ public class HealAllPolygonsWrongOrientationErrorTest { CityDoctorModel model = TestUtil.loadCityModel(path, config); Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealConsecutivePointsSameErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealConsecutivePointsSameErrorTest.java index 0e530923d65b4df25d5b53650a9f486ce3a49c61..efd83d4805520fcfa054826c4ac143f2e407102e 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealConsecutivePointsSameErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealConsecutivePointsSameErrorTest.java @@ -26,11 +26,11 @@ public class HealConsecutivePointsSameErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_R_DUPLICATE_POINT)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_R_DUPLICATE_POINT)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealHoleOutsideErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealHoleOutsideErrorTest.java index 50ca0b4724383000d63d397cba99c30eeadc0b8b..909bd46c1cf59af53afacf6de12040ca3a85bca6 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealHoleOutsideErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealHoleOutsideErrorTest.java @@ -25,11 +25,11 @@ public class HealHoleOutsideErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Building building = model.getBuildings().get(0); + Building building = model.getBuildings().toList().get(0); Assert.assertTrue(building.containsError(CheckId.C_GE_P_HOLE_OUTSIDE)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(building.containsError(CheckId.C_GE_P_HOLE_OUTSIDE)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealMissingSolidTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealMissingSolidTest.java index 0b064845520f1581bb84717742cdb6b60c523d1d..07adf8c1e520aaaa8d5595768de7217957f5a7c1 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealMissingSolidTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealMissingSolidTest.java @@ -138,7 +138,7 @@ public class HealMissingSolidTest { model.saveAs(createSolidFile.toString(), false); CityDoctorModel parsedModel = CityGmlParser.parseCityGmlFile(createSolidFile.toString(), config.getParserConfiguration()); - Building building = parsedModel.getBuildings().get(0); + Building building = parsedModel.getBuildings().toList().get(0); assertEquals(1, building.getGeometries().size()); Geometry geometry2 = building.getGeometries().get(0); assertEquals(GeometryType.SOLID, geometry2.getType()); @@ -162,7 +162,7 @@ public class HealMissingSolidTest { new RequirementConfiguration(false)); CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/SimpleSolid_SrefBS_withoutSolid.gml", config.getParserConfiguration()); - Building b = model.getBuildings().get(0); + Building b = model.getBuildings().toList().get(0); assertTrue(b.getGeometries().isEmpty()); Checker c = new Checker(config, model); c.runChecks(); diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealNonManifoldEdgeErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealNonManifoldEdgeErrorTest.java index 110254116dab3ee0e896f89a21555acb72e9f3ad..2bfca2e739f0002a9b23ffc5284d1ea9f1240715 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealNonManifoldEdgeErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealNonManifoldEdgeErrorTest.java @@ -25,11 +25,11 @@ public class HealNonManifoldEdgeErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_S_NON_MANIFOLD_EDGE)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_S_NON_MANIFOLD_EDGE)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPlanarPolygonErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPlanarPolygonErrorTest.java index 7b5576bdf330e218e813c323b28ada149660d73e..5359f2d6b1164dc4aff26c8f216c4e83f4706474 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPlanarPolygonErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPlanarPolygonErrorTest.java @@ -43,12 +43,12 @@ public class HealPlanarPolygonErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_P_NON_PLANAR)); Healer healer = new Healer(c); healer.setNumberOfIterations(2); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_P_NON_PLANAR)); diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWithoutSurfaceTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWithoutSurfaceTest.java index 28e6832c7b5b721f47d7a40d844f4c0c4b295603..0ccc24f0ccb65a362dbdfe7f88f65e87e747a8c6 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWithoutSurfaceTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWithoutSurfaceTest.java @@ -35,11 +35,11 @@ public class HealPolygonWithoutSurfaceTest { Checker c = new Checker(config, model); c.runChecks(); - Building building = model.getBuildings().get(0); + Building building = model.getBuildings().toList().get(0); Assert.assertTrue(building.containsError(CheckId.C_SE_POLYGON_WITHOUT_SURFACE)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(building.containsError(CheckId.C_SE_POLYGON_WITHOUT_SURFACE)); @@ -49,7 +49,7 @@ public class HealPolygonWithoutSurfaceTest { CityDoctorModel loadedModel = TestUtil.loadCityModel(outputFile.toString(), config); c = new Checker(config, loadedModel); c.runChecks(); - building = loadedModel.getBuildings().get(0); + building = loadedModel.getBuildings().toList().get(0); Assert.assertFalse(building.containsError(CheckId.C_SE_POLYGON_WITHOUT_SURFACE)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWrongOrientationErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWrongOrientationErrorTest.java index 7f640b9690246f4089a6ae2fb335916c8a00b087..9d8e1b8da5bc8f06a1bb9ae630cedc4415516ae7 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWrongOrientationErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealPolygonWrongOrientationErrorTest.java @@ -41,11 +41,11 @@ public class HealPolygonWrongOrientationErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_S_POLYGON_WRONG_ORIENTATION)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_S_POLYGON_WRONG_ORIENTATION)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingNotClosedErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingNotClosedErrorTest.java index 6622e3554e2d7b51c9cae1acc9c4e5b1c1727ce0..e8f03e12491b30431cd1fa96029b36e8efc63faf 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingNotClosedErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingNotClosedErrorTest.java @@ -25,11 +25,11 @@ public class HealRingNotClosedErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_R_NOT_CLOSED)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_R_NOT_CLOSED)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingSelfIntErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingSelfIntErrorTest.java index 8a33573b70cbd02ac734d900e0fbf0321d0724da..4408e1226c9b235ba9a2bbc78be96c71ef15155b 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingSelfIntErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealRingSelfIntErrorTest.java @@ -190,11 +190,11 @@ public class HealRingSelfIntErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION)); } @@ -208,11 +208,11 @@ public class HealRingSelfIntErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION)); } @@ -228,11 +228,11 @@ public class HealRingSelfIntErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_R_SELF_INTERSECTION)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSameOrientationErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSameOrientationErrorTest.java index e5b64193dd4c2664e32cbd33b65a3e02bb169bbd..f0802787cf00831c6d04c58ad165b4e83e330f43 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSameOrientationErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSameOrientationErrorTest.java @@ -26,11 +26,11 @@ public class HealSameOrientationErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Assert.assertTrue(geom.containsError(CheckId.C_GE_P_ORIENTATION_RINGS_SAME)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_P_ORIENTATION_RINGS_SAME)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSolidNotClosedErrorTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSolidNotClosedErrorTest.java index 5a8713a8664a8429f9b8550f9aaad5abe6d99f65..06e4d9e1f09b6991bdfff09db9446ca748092181 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSolidNotClosedErrorTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealSolidNotClosedErrorTest.java @@ -439,7 +439,7 @@ public class HealSolidNotClosedErrorTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); geom.updateVertices(); for (Vertex v : geom.getVertices()) { v.setX(v.getX() - 10); @@ -449,7 +449,7 @@ public class HealSolidNotClosedErrorTest { Healer healer = new Healer(c); //healer.setNumberOfIterations(2); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); Assert.assertFalse(geom.containsError(CheckId.C_GE_S_NOT_CLOSED)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealTooFewPointsTest.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealTooFewPointsTest.java index eac3472b3097e9314a33bb5022dbbd62e0334519..8d22d6e6d71bb106ea2912b6af0dcb82921a84f7 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealTooFewPointsTest.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/HealTooFewPointsTest.java @@ -27,11 +27,11 @@ public class HealTooFewPointsTest { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); assertTrue(geom.containsError(CheckId.C_GE_R_TOO_FEW_POINTS)); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); assertFalse(geom.containsError(CheckId.C_GE_R_TOO_FEW_POINTS)); } diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestHealer.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestHealer.java index a36ce00d1f8fd5dc57c7e4f01fc46000ef87fd62..63ccbd0519033df305c12372b7eff5a7f53b3391 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestHealer.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestHealer.java @@ -45,7 +45,7 @@ public class TestHealer { c.runChecks(); Building b = null; - for (Building building : model.getBuildings()) { + for (Building building : model.getBuildings().toList()) { if (building.getGmlId().getGmlString().equals("DEBE08YYF0004KZs")) { b = building; break; @@ -125,8 +125,8 @@ public class TestHealer { c.runChecks(); Healer healer = new Healer(c); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); - healer.healCityObject(model.getBuildings().get(0)); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); @@ -151,11 +151,11 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Healer healer = new Healer(c); healer.setNumberOfIterations(33); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); @@ -171,10 +171,10 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Healer healer = new Healer(c); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); @@ -190,11 +190,11 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Healer healer = new Healer(c); healer.setNumberOfIterations(83); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); @@ -210,11 +210,11 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Healer healer = new Healer(c); healer.setNumberOfIterations(165); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); @@ -241,7 +241,7 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Building b = model.getBuildings().get(0); + Building b = model.getBuildings().toList().get(0); Healer healer = new Healer(c); healer.healCityObject(b); c.runChecks(); @@ -261,11 +261,11 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Healer healer = new Healer(c); healer.setNumberOfIterations(45); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); @@ -297,10 +297,10 @@ public class TestHealer { Checker c = new Checker(config, model); c.runChecks(); - Geometry geom = model.getBuildings().get(0).getGeometries().get(0); + Geometry geom = model.getBuildings().toList().get(0).getGeometries().get(0); Healer healer = new Healer(c); healer.setNumberOfIterations(100); - healer.healCityObject(model.getBuildings().get(0)); + healer.healCityObject(model.getBuildings().toList().get(0)); c.runChecks(); assertFalse(geom.containsAnyError()); diff --git a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestUtil.java b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestUtil.java index ca21944ccbe7f6ad47383cbf987d7b0a719e44fd..72a2450f86cbed1d2e6adc7eab79028e8d84d332 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestUtil.java +++ b/CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/TestUtil.java @@ -38,15 +38,15 @@ public class TestUtil { if (gmlId == null) { return null; } - Polygon result = getPolygonById(gmlId, model.getBuildings()); + Polygon result = getPolygonById(gmlId, model.getBuildings().toList()); if (result != null) { return result; } - result = getPolygonById(gmlId, model.getVegetation()); + result = getPolygonById(gmlId, model.getVegetation().toList()); if (result != null) { return result; } - return getPolygonById(gmlId, model.getTransportation()); + return getPolygonById(gmlId, model.getTransportation().toList()); } private static Polygon getPolygonById(String gmlId, List features) { @@ -85,17 +85,17 @@ public class TestUtil { if (featureId == null) { return null; } - for (CityObject co : model.getBuildings()) { + for (CityObject co : model.getBuildings().toList()) { if (featureId.equals(co.getGmlId().getGmlString())) { return co; } } - for (CityObject co : model.getTransportation()) { + for (CityObject co : model.getTransportation().toList()) { if (featureId.equals(co.getGmlId().getGmlString())) { return co; } } - for (CityObject co : model.getVegetation()) { + for (CityObject co : model.getVegetation().toList()) { if (featureId.equals(co.getGmlId().getGmlString())) { return co; } diff --git a/CityDoctorParent/Extensions/CityDoctorHealerGUI/pom.xml b/CityDoctorParent/Extensions/CityDoctorHealerGUI/pom.xml index 8eb1cfeeaf651e273121b1da6c586d02b89e23aa..7368ea56d9515f15c9c4287e2b2598aa00767e9b 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealerGUI/pom.xml +++ b/CityDoctorParent/Extensions/CityDoctorHealerGUI/pom.xml @@ -7,7 +7,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 ../../pom.xml CityDoctorHealerGUI diff --git a/CityDoctorParent/Extensions/CityDoctorHealerGUI/src/main/java/de/hft/stuttgart/citydoctor2/healer/gui/HealerController.java b/CityDoctorParent/Extensions/CityDoctorHealerGUI/src/main/java/de/hft/stuttgart/citydoctor2/healer/gui/HealerController.java index 62eccfd86cba9671e15df916939da6c9df8572d0..5668a4570069b12de7daba80d2ebf29eeaf91e92 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealerGUI/src/main/java/de/hft/stuttgart/citydoctor2/healer/gui/HealerController.java +++ b/CityDoctorParent/Extensions/CityDoctorHealerGUI/src/main/java/de/hft/stuttgart/citydoctor2/healer/gui/HealerController.java @@ -674,9 +674,7 @@ public class HealerController { // triangle area is too small, ignore return; } - for (Building b : model.getBuildings()) { - MeshGenerator.replaceGeometryWithMeshedGeometry(b, area); - } + model.getBuildings().forEach(building -> MeshGenerator.replaceGeometryWithMeshedGeometry(building, area)); } catch (NumberFormatException e) { // no real number was inserted, do nothing } diff --git a/CityDoctorParent/Extensions/CityDoctorHealerGenetic/pom.xml b/CityDoctorParent/Extensions/CityDoctorHealerGenetic/pom.xml index 352b8af31ec441acd47ac26c80fe0a1b5d885110..280bad626a5cc32576f63953edd9bfc249e18914 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealerGenetic/pom.xml +++ b/CityDoctorParent/Extensions/CityDoctorHealerGenetic/pom.xml @@ -4,7 +4,7 @@ de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 ../../pom.xml CityDoctorHealerGenetic diff --git a/CityDoctorParent/Extensions/CityDoctorHealerGenetic/src/main/java/de/hft/stuttgart/citydoctor2/healer/genetic/gui/GeneticsGUI.java b/CityDoctorParent/Extensions/CityDoctorHealerGenetic/src/main/java/de/hft/stuttgart/citydoctor2/healer/genetic/gui/GeneticsGUI.java index 894e4c7b02589a59a27fb14fd04339e3250c9ba0..c9a65976c3bfb2a0db457e9e3b06ebc87837da74 100644 --- a/CityDoctorParent/Extensions/CityDoctorHealerGenetic/src/main/java/de/hft/stuttgart/citydoctor2/healer/genetic/gui/GeneticsGUI.java +++ b/CityDoctorParent/Extensions/CityDoctorHealerGenetic/src/main/java/de/hft/stuttgart/citydoctor2/healer/genetic/gui/GeneticsGUI.java @@ -329,7 +329,7 @@ public class GeneticsGUI extends View { parserConfig); currentChecker = new Checker(model1); currentChecker.runChecks(); - Building building = model1.getBuildings().get(0); + Building building = model1.getBuildings().toList().getFirst(); currentGeometry = building.getGeometries().get(0); currentFeature = building; showCurrentGeometry(); diff --git a/CityDoctorParent/pom.xml b/CityDoctorParent/pom.xml index 84bc1df25c5d4d94f4944e7658f82a353383d70b..b5198f83b37d839a77d49dd77d9d5806dcd0f2cc 100644 --- a/CityDoctorParent/pom.xml +++ b/CityDoctorParent/pom.xml @@ -5,7 +5,7 @@ 4.0.0 de.hft.stuttgart CityDoctorParent - 3.17.3 + 3.18.0 pom CityDoctorParent @@ -242,6 +242,21 @@ earcut4j 2.2.2 + + org.orbisgis + h2gis + 2.2.3 + + + com.github.ben-manes.caffeine + caffeine + 3.2.2 + + + com.zaxxer + HikariCP + 7.0.2 + @@ -267,6 +282,17 @@ info.picocli picocli + + org.apache.logging.log4j + log4j-slf4j18-impl + 2.18.0 + test + + + junit + junit + test + @@ -277,10 +303,10 @@ Extensions/CityDoctorGUI - Extensions/CityDoctorAutoPro - Extensions/CityDoctorHealer - Extensions/CityDoctorHealerGenetic - Extensions/CityDoctorHealerGUI + + + + \ No newline at end of file