Commit e178e81e authored by Luna Riegel's avatar Luna Riegel
Browse files

Refactor: Connect GeoDB to internal model

parent 28c42d2d
Pipeline #12004 failed with stage
in 1 minute and 34 seconds
package de.hft.stuttgart.citydoctor2.database;
public class CacheManager {
private static FeatureCache cache = null;
public static CityObjectCache getFeatureCache(String filename) {
if (cache == null){
cache = new FeatureCache(filename);
} else {
cache.changeFileName(filename);
}
return cache;
}
public static CityObjectCache getUnconnectedCache(){
return new UnconnectedCache();
}
}
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 {
void put(CityObject cityObject);
CityObject get(GmlId id);
void replace(GmlId id, CityObject cityObject);
Stream<CityObject> getStream(List<GmlId> ids);
int getFeatureCount();
}
......@@ -5,6 +5,8 @@ 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 javafx.scene.control.Alert;
import org.apache.commons.lang3.SerializationException;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -25,39 +27,49 @@ public class DatabaseHandler {
private static final Logger logger = LogManager.getLogger(DatabaseHandler.class);
private static final String DB_NAME = "cd_db";
private final String fileName;
static{
// Creates the Database at initialization
try {
H2GISDBFactory.createSpatialDataBase(DB_NAME,
true, ";FILE_LOCK=SOCKET");
private DatabaseHandler() {
} catch (Exception e) {
logger.fatal("FATAL ERROR: Creation of embedded database failed!");
logger.fatal(e.getMessage());
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("FATAL ERROR");
alert.setHeaderText("FATAL ERROR");
alert.setContentText("Creation of embedded database failed!");
alert.showAndWait();
}
}
public DatabaseHandler(String fileName){
this.fileName = fileName;
setupFeaturesTable();
}
/**
* Sets up a new, empty embedded database. Will override an existing embedded database.
*/
public static void setupDatabase() {
try {
H2GISDBFactory.createSpatialDataBase(DB_NAME,
true, ";FILE_LOCK=SOCKET");
setupFeaturesTable();
} catch (Exception e) {
logger.fatal("FATAL ERROR: Creation of embedded database failed!");
logger.fatal(e.getMessage());
// TODO: implement popup and shutdown
}
}
public static void setupFeaturesTable() {
public void setupFeaturesTable() {
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement dropPs = con.prepareStatement("DROP TABLE IF EXISTS features")) {
try (PreparedStatement dropPs = con.prepareStatement(String.format("DROP TABLE IF EXISTS %s", fileName))) {
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, type VARCHAR(255) NOT NULL)")) {
try (PreparedStatement createPs = con.prepareStatement(String.format("CREATE TABLE %s (gmlid VARCHAR(255)" +
" PRIMARY KEY, bbox GEOMETRY, data BLOB, type VARCHAR(255) NOT NULL)", fileName))) {
createPs.executeUpdate();
if (logger.isDebugEnabled()) {
logger.debug("Created features table");
......@@ -74,9 +86,9 @@ public class DatabaseHandler {
* Saves a CityObject to the embedded database, updating an existing entry if it exists.
* @param co the CityObject
*/
public static void marshallCityObject(CityObject co) {
public void marshallCityObject(CityObject co) {
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("MERGE INTO features VALUES (?, ?, ?, ?)")) {
try (PreparedStatement ps = con.prepareStatement(String.format("MERGE INTO %s VALUES (?, ?, ?, ?)", fileName))) {
ps.setString(1, co.getGmlId().toString());
String bbox = BoundingBox.of(co).to2DWkt();
ps.setString(2, bbox);
......@@ -84,14 +96,20 @@ public class DatabaseHandler {
logger.debug("Attempting to serialize CityObject: {} ", co);
}
ps.setString(4, co.getClass().getName());
byte[] bytes = SerializationUtils.serialize(co);
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ps.setBinaryStream(3, bis, bytes.length);
ps.executeUpdate();
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("Saving of city object to embedded database failed!");
logger.debug(e.getMessage());
logger.error("Saving of city object {} to embedded database failed!", co.getGmlId());
logger.error(e.getMessage());
}
}
......@@ -100,9 +118,10 @@ public class DatabaseHandler {
* @param id the gmlId of the requested Feature
* @return the Feature, or null if no entry was found
*/
public static CityObject unmarshallCityObject(GmlId id) {
public CityObject unmarshallCityObject(GmlId id) {
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("SELECT gmlid, bbox, data, type FROM features WHERE gmlid = ?")) {
try (PreparedStatement ps = con.prepareStatement(String.format(
"SELECT gmlid, bbox, data, type FROM %s WHERE gmlid = ?", fileName))) {
ps.setString(1, id.toString());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
......@@ -129,10 +148,10 @@ public class DatabaseHandler {
return null;
}
public static List<CityObject> getAllCityObjects() {
public List<CityObject> getAllCityObjects() {
List<CityObject> cos = new ArrayList<>();
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("SELECT gmlid, bbox, data, type FROM features")) {
try (PreparedStatement ps = con.prepareStatement(String.format("SELECT gmlid, bbox, data, type FROM %s", fileName))) {
ResultSet rs = ps.executeQuery();
cos.addAll(retrieveCityObjects(rs));
}
......@@ -143,10 +162,11 @@ public class DatabaseHandler {
return cos;
}
public static List<GmlId> getAllGmlIds() {
public List<GmlId> getAllGmlIds() {
List<GmlId> cos = new ArrayList<>();
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("SELECT gmlid FROM features")) {
try (PreparedStatement ps = con.prepareStatement(String.format("SELECT gmlid FROM %s", fileName))) {
ps.setString(1, fileName);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
cos.add(new GmlId(rs.getString("gmlid")));
......@@ -159,15 +179,16 @@ public class DatabaseHandler {
return cos;
}
public static List<GmlId> getBufferIntersectingObjects(CityObject co, double bufferSize) {
public List<GmlId> getBufferIntersectingObjects(CityObject co, double bufferSize) {
return getBufferIntersectingObjects(co.getGmlId(), bufferSize);
}
public static List<GmlId> getBufferIntersectingObjects(GmlId gmlID, double bufferSize) {
public List<GmlId> getBufferIntersectingObjects(GmlId gmlID, double bufferSize) {
List<GmlId> intersectingObjects = new ArrayList<>();
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
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 <> ?")) {
try (PreparedStatement ps = con.prepareStatement(String.format("SELECT gmlid FROM %s AS tab1" +
" WHERE ST_INTERSECTS(ST_BUFFER(tab1.bbox,?), (SELECT bbox FROM %s WHERE gmlid = ?)) " +
"AND tab1.gmlid <> ?", fileName, fileName))) {
ps.setDouble(1, bufferSize);
ps.setString(2, gmlID.toString());
ps.setString(3, gmlID.toString());
......@@ -183,16 +204,17 @@ public class DatabaseHandler {
return intersectingObjects;
}
public static List<GmlId> getBBoxIntersectingObjects(CityObject co) {
public List<GmlId> getBBoxIntersectingObjects(CityObject co) {
return getBBoxIntersectingObjects(co.getGmlId());
}
public static List<GmlId> getBBoxIntersectingObjects(GmlId id) {
public List<GmlId> getBBoxIntersectingObjects(GmlId id) {
List<GmlId> intersectingObjects = new ArrayList<>();
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
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 <> ?")) {
try (PreparedStatement ps = con.prepareStatement(String.format("SELECT gmlid FROM %s AS tab1" +
" WHERE ST_INTERSECTS(tab1.bbox, (SELECT bbox FROM %s WHERE gmlid = ?)) AND tab1.gmlid <> ?",
fileName, fileName))) {
ps.setString(1, id.toString());
ps.setString(2, id.toString());
ResultSet rs = ps.executeQuery();
......@@ -208,11 +230,11 @@ public class DatabaseHandler {
}
public static int getFeatureCount() {
public int getFeatureCount() {
int count = -1;
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(gmlid) AS nr FROM features")) {
try (PreparedStatement ps = con.prepareStatement(String.format("SELECT COUNT(gmlid) AS nr FROM %s", fileName))) {
ResultSet rs = ps.executeQuery();
if (rs.next()) {
count = rs.getInt("nr");
......@@ -225,7 +247,7 @@ public class DatabaseHandler {
return count;
}
private static List<CityObject> retrieveCityObjects(ResultSet rs) throws SQLException {
private List<CityObject> retrieveCityObjects(ResultSet rs) throws SQLException {
List<CityObject> cos = new ArrayList<>();
while (rs.next()) {
try (InputStream is = rs.getBinaryStream("data")) {
......
package de.hft.stuttgart.citydoctor2.database;
import com.github.benmanes.caffeine.cache.Cache;
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 de.hft.stuttgart.citydoctor2.utils.visitors.CityObjectCollector;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
/**
* Cache for CityObjects
*/
public class FeatureCache{
public class FeatureCache implements CityObjectCache{
private final LoadingCache<GmlId, CityObject> cache;
private DatabaseHandler handler;
private final Map<String, DatabaseHandler> handlerList = new HashMap<>();
private final Cache<GmlId, CityObject> subCache;
public FeatureCache() {
FeatureCache(String fileName) {
handler = new DatabaseHandler(fileName);
handler.setupFeaturesTable();
cache = Caffeine.newBuilder().maximumSize(3000).removalListener((GmlId key, CityObject value, RemovalCause cause) -> {
if (value != null && cause.wasEvicted()) {
DatabaseHandler.marshallCityObject(value);
handler.marshallCityObject(value);
}
}).build(DatabaseHandler::unmarshallCityObject);
subCache = Caffeine.newBuilder().maximumSize(250).build();
DatabaseHandler.setupDatabase();
}).build(handler::unmarshallCityObject);
}
@Override
public void put(CityObject cityObject) {
DatabaseHandler.marshallCityObject(cityObject);
handler.marshallCityObject(cityObject);
cache.put(cityObject.getGmlId(), cityObject);
}
@Override
public CityObject get(GmlId id) {
return cache.get(id);
}
public void changeFileName(String fileName){
handler = handlerList.computeIfAbsent(fileName, k -> {
DatabaseHandler handler1 = new DatabaseHandler(fileName);
handler1.setupFeaturesTable();
return handler1;
});
}
@Override
public void replace(GmlId id, CityObject cityObject) {
cache.invalidate(id);
put(cityObject);
}
@Override
public Stream<CityObject> getStream(List<GmlId> gmlIds) {
return gmlIds.stream().map(this::get);
}
/**
* Gets a non-top-level CityObject directly. Only use this in situations where directly accessing the object is required
* and access via the top-level CityObject is impossible or highly inefficient, e.g. rendering the associated object
* of a CityObjectNode.
* @param coa the adapter object of the subpart
* @return the associated CityObject
*/
public CityObject getSubPart(SubPartAdapter coa) {
CityObject co = subCache.getIfPresent(coa.getFeatureId());
if (co == null) {
return buildAndGetSubPart(coa);
}
else return co;
}
/**
*
* @param coa
* @return
*/
private CityObject buildAndGetSubPart(SubPartAdapter coa) {
CityObject parent = cache.get(coa.getTopLevelId());
if (parent == null) {
throw new IllegalStateException("CityObjectAdapter has non-existent parent - GmlId: " + coa.getTopLevelId());
}
CityObjectCollector collector = new CityObjectCollector();
parent.accept(collector);
collector.getCityObjects().forEach(cityObject -> subCache.put(cityObject.getGmlId(), cityObject));
CityObject co = subCache.getIfPresent(coa.getFeatureId());
if (co == null) {
throw new IllegalStateException("CityObjectAdapter has non-existent feature - GmlId: " + coa.getFeatureId() +
", parent GmlId: " + coa.getTopLevelId());
}
return co;
}
public List<CityObject> get(List<GmlId> ids) {
List<CityObject> features = new ArrayList<>();
for (GmlId id : ids) {
features.add(cache.get(id));
}
return features;
@Override
public int getFeatureCount() {
return handler.getFeatureCount();
}
......
package de.hft.stuttgart.citydoctor2.database;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
/**
* A lightweight, unmanaged CityObjectCache that is not connected with the embedded Database.
*/
public class UnconnectedCache implements CityObjectCache{
private final Map<GmlId, CityObject> cache;
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) {
// Not needed
}
@Override
public Stream<CityObject> getStream(List<GmlId> ids) {
return cache.values().stream().filter(c -> ids.contains(c.getGmlId()));
}
@Override
public int getFeatureCount() {
return cache.size();
}
}
......@@ -170,11 +170,27 @@ public class BoundingBox {
}
/**
* Returns a WKT polygon representation in 2D of this bbox
*
* @return WKT String of this bbox's shadow
* 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.
* <p/>
* 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();
......
......@@ -21,11 +21,13 @@ 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.FeatureCache;
import de.hft.stuttgart.citydoctor2.database.CacheManager;
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;
import de.hft.stuttgart.quality.model.types.ValidationPlan;
import org.apache.commons.io.FilenameUtils;
import org.citygml4j.core.model.CityGMLVersion;
import org.citygml4j.core.model.core.CityModel;
......@@ -64,9 +66,13 @@ public class CityDoctorModel {
private boolean isValidated = false;
private ValidationPlan plan;
private CityGMLVersion cityGMLVersion;
private final FeatureCache cache;
private final CityObjectCache cache;
public CityDoctorModel(ParserConfiguration config, File file) {
this(config, file, CacheManager.getFeatureCache(FilenameUtils.removeExtension(file.getName())));
}
public CityDoctorModel(ParserConfiguration config, File file, CityObjectCache cache) {
if (config == null) {
throw new IllegalArgumentException("Parser configuration may not be null");
}
......@@ -83,7 +89,7 @@ public class CityDoctorModel {
cityfurniture = new ArrayList<>();
genericObjects = new ArrayList<>();
globalErrors = new ArrayList<>();
cache = new FeatureCache();
this.cache = cache;
}
public boolean isValidated() {
......@@ -368,7 +374,7 @@ public class CityDoctorModel {
return cModel;
}
public FeatureCache getCache(){
public CityObjectCache getCache(){
return cache;
}
......
......@@ -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;
......@@ -51,8 +52,11 @@ public class ImplicitGeometryHolder extends Geometry {
return igh;
}
public static void resolveDeferredObjects() {
public static void resolveDeferredObjects(CityObjectCache cache) {
Set<GmlId> 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();
......
......@@ -27,7 +27,7 @@ public class LibraryObject extends Geometry {
@Serial
private static final long serialVersionUID = -50293435187454911L;
private static Map<String, LibraryObject> libraryObjects = new ConcurrentHashMap<>();
private static final Map<String, LibraryObject> libraryObjects = new ConcurrentHashMap<>();
public static LibraryObject of(Path path, ParserConfiguration config) {
if (libraryObjects.containsKey(path.toString())) {
......@@ -69,7 +69,7 @@ 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));
......@@ -86,7 +86,7 @@ public class LibraryObject extends Geometry {
private static Geometry parseZipEntry(CityGmlZipEntry entry, ParserConfiguration config) {
Geometry geo = null;
try {
entry.loadEntry(config);
entry.loadEntry(config, true);
geo = getProtoGeometry(entry.getModel());
} catch (InvalidGmlFileException e) {
logger.error(e.getStackTrace());
......
......@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.hft.stuttgart.citydoctor2.database.CacheManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.citygml4j.core.model.CityGMLVersion;
......@@ -173,19 +174,27 @@ public class Citygml3FeatureMapper extends ObjectWalker {
private List<ResolvableReference> references = new ArrayList<>();
private Map<Vertex, Vertex> vertexMap = new HashMap<>();
public Citygml3FeatureMapper(ParserConfiguration config, Path path) {
public Citygml3FeatureMapper(ParserConfiguration config, Path path, boolean nested) {
this.config = config;
this.directory = path.getParent();
model = new CityDoctorModel(config, path.toFile());
if (nested){
model = new CityDoctorModel(config, path.toFile(), CacheManager.getUnconnectedCache());
} else {
model = new CityDoctorModel(config, path.toFile());
}
neighborDistance = 1.8d / Math.pow(10, config.getNumberOfRoundingPlaces());
zipEntry = null;
}
public Citygml3FeatureMapper(ParserConfiguration config, CityGmlZipEntry entry) {
public Citygml3FeatureMapper(ParserConfiguration config, CityGmlZipEntry entry, boolean nested) {
this.config = config;
this.directory = null;
this.zipEntry = entry;
model = new CityDoctorModel(config, Path.of(entry.getEntrySubPath()).toFile());
if (nested){
model = new CityDoctorModel(config, Path.of(entry.getEntrySubPath()).toFile(), CacheManager.getUnconnectedCache());
} else {
model = new CityDoctorModel(config, Path.of(entry.getEntrySubPath()).toFile());
}
neighborDistance = 1.8d / Math.pow(10, config.getNumberOfRoundingPlaces());
}
......
......@@ -30,6 +30,7 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -167,24 +168,102 @@ public class CityGmlParser {
}
return context;
}
//TODO: Implement resolving of library objects with database
public static CityDoctorModel parseCityGmlFileSilently(String file, ParserConfiguration config)
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* <p/>
* The nested parse uses an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}, which
* is not connected to the database.
* <p/>
* 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}.
* <p/>
* 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}.
* <p/>
* 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}.
* <p/>
* 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}.
* <p/>
* 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 nested If nested is enabled the parser will use an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}
* @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 nested)
throws CityGmlParseException, InvalidGmlFileException {
CityGMLContext context = getContext();
Path file = Paths.get(filePath);
if (config.getValidate()) {
......@@ -202,7 +281,7 @@ public class CityGmlParser {
if (l != null) {
ois.addListener(l::updateProgress);
}
return readAndKeepFeatures(config, file, in, ois, verbose);
return readAndKeepFeatures(config, file, in, ois, verbose, nested);
}
} catch (CityGMLReadException | IOException e) {
throw new CityGmlParseException("Failed to read CityGML file", e);
......@@ -210,12 +289,13 @@ public class CityGmlParser {
}
public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config)
public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l)
throws CityGmlParseException, InvalidGmlFileException, IOException {
return parseCityGmlZipEntry(entry, config, null);
return parseCityGmlZipEntry(entry, config, l, false);
}
public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config, ProgressListener l)
public static CityDoctorModel parseCityGmlZipEntry(CityGmlZipEntry entry, ParserConfiguration config,
ProgressListener l, boolean nested)
throws CityGmlParseException, InvalidGmlFileException, IOException {
CityGMLContext context = getContext();
......@@ -230,15 +310,12 @@ public class CityGmlParser {
}
}
return decompressAndParseCityGmlEntry(entry, config, l, context);
return decompressAndParseCityGmlEntry(entry, config, l, context, nested);
}
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)
public static CityDoctorModel decompressAndParseCityGmlEntry(CityGmlZipEntry entry, ParserConfiguration config,
ProgressListener l, CityGMLContext context, boolean nested)
throws CityGmlParseException {
try (CityGmlZipEntryFile entryFile = new CityGmlZipEntryFile(entry)) {
......@@ -250,7 +327,7 @@ public class CityGmlParser {
if (l != null) {
ois.addListener(l::updateProgress);
}
return readAndKeepFeatures(config, entry, in, ois, false);
return readAndKeepFeatures(config, entry, in, ois, false, nested);
}
} catch (CityGMLReadException | IOException e) {
throw new CityGmlParseException("Failed to read CityGML file", e);
......@@ -260,8 +337,10 @@ public class CityGmlParser {
}
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);
CityGMLInputFactory inputFactory, ObservedInputStream ois,
boolean verbose, boolean nested)
throws CityGMLReadException {
return readAndKeepModel(new Citygml3FeatureMapper(config, entry, nested), inputFactory, ois, verbose);
}
private static List<String> validateStream(InputStream vis, CityGMLContext context) throws CityGmlParseException {
......@@ -374,7 +453,7 @@ 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);
}
......@@ -395,7 +474,7 @@ public class CityGmlParser {
private static void streamAndDiscardFeatures(CityGmlZipEntry entry, ParserConfiguration config, ObservedInputStream ois,
CityGmlConsumer cityObjectConsumer, String outputFile) throws CityGMLReadException {
Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, entry);
Citygml3FeatureMapper mapper = new Citygml3FeatureMapper(config, entry, false);
readAndDiscardModel(mapper, ois, cityObjectConsumer, outputFile);
}
......@@ -485,8 +564,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 nested) throws CityGMLReadException {
return readAndKeepModel(new Citygml3FeatureMapper(config, file, nested), inputFactory, ois, verbose);
}
private static CityDoctorModel readAndKeepModel(Citygml3FeatureMapper mapper, CityGMLInputFactory inputFactory,
......@@ -518,10 +598,13 @@ public class CityGmlParser {
CityModel cModel = mapper.getModel().getCityModel();
// remove those that should have been parsed
List<AbstractCityObject> parsedCityObjects = mapper.getModel().createFeatureStream()
logger.info("Getting parsed object from CityDoctorModel");
List<AbstractCityObject> parsedCityObjects = mapper.getModel().createFeatureStream().filter(Objects::nonNull)
.map(CityObject::getGmlObject).toList();
logger.info("Removing all parsed city objects from acos");
acos.removeAll(parsedCityObjects);
// re-add all not parsed objects
logger.info("Resolving HRefs");
for (AbstractCityObject aco : acos) {
cModel.getCityObjectMembers().add(new AbstractCityObjectProperty(aco));
}
......@@ -530,7 +613,7 @@ public class CityGmlParser {
mapper.getModel().getNumberOfFeatures());
}
// After parsing is complete, try to resolve deferred RelativeGeometries
ImplicitGeometryHolder.resolveDeferredObjects();
ImplicitGeometryHolder.resolveDeferredObjects(mapper.getModel().getCache());
mapper.setCityGMLVersion(version);
return mapper.getModel();
}
......
......@@ -46,7 +46,15 @@ public class CityGmlZipEntry implements Serializable {
* @param config Parser configuration for this model
*/
public void loadEntry(ParserConfiguration config) {
loadEntry(config, null);
loadEntry(config, null, false);
}
public void loadEntry(ParserConfiguration config, boolean nested) {
loadEntry(config, null, nested);
}
public void loadEntry(ParserConfiguration config, ProgressListener progressListener) {
loadEntry(config, progressListener, false);
}
/**
......@@ -58,7 +66,7 @@ public class CityGmlZipEntry implements Serializable {
* @param config Parser configuration for this model
* @param l ProgressListener for tracking parsing progress
*/
public void loadEntry(ParserConfiguration config, ProgressListener l) {
public void loadEntry(ParserConfiguration config, ProgressListener l, boolean nested) {
if (inMemory) {
return;
}
......@@ -67,7 +75,7 @@ public class CityGmlZipEntry implements Serializable {
return;
}
try {
this.model = CityGmlParser.parseCityGmlZipEntry(this, config, l);
this.model = CityGmlParser.parseCityGmlZipEntry(this, config, l, nested);
this.inMemory = true;
} catch (CityGmlParseException | InvalidGmlFileException e) {
logger.error(e);
......
......@@ -18,7 +18,6 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import org.citygml4j.core.model.building.AbstractBuilding;
import org.h2gis.functions.factory.H2GISDBFactory;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
......@@ -33,15 +32,13 @@ import static org.junit.Assert.fail;
public class DataBaseHandlerTest {
@BeforeClass
public static void setUpBeforeClass() {
DatabaseHandler.setupDatabase();
}
private DatabaseHandler handler;
@Before
public void resetDatabase() {
try {
DatabaseHandler.setupFeaturesTable();
handler = new DatabaseHandler("test");
handler.setupFeaturesTable();
} catch (Exception e) {
fail(e.getMessage());
}
......@@ -63,14 +60,14 @@ public class DataBaseHandlerTest {
Building b3 = new Building();
b3.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID, Lod.LOD3));
DatabaseHandler.marshallCityObject(b);
DatabaseHandler.marshallCityObject(b2);
DatabaseHandler.marshallCityObject(b3);
assertEquals(3, DatabaseHandler.getFeatureCount());
handler.marshallCityObject(b);
handler.marshallCityObject(b2);
handler.marshallCityObject(b3);
assertEquals(3, handler.getFeatureCount());
List<CityObject> objects = DatabaseHandler.getAllCityObjects();
List<CityObject> objects = handler.getAllCityObjects();
assertEquals(3, objects.size());
assertEquals(3, DatabaseHandler.getFeatureCount());
assertEquals(3, handler.getFeatureCount());
}
......@@ -139,17 +136,17 @@ public class DataBaseHandlerTest {
geom3.updateEdgesAndVertices();
b3.addGeometry(geom3);
DatabaseHandler.marshallCityObject(b);
DatabaseHandler.marshallCityObject(b2);
DatabaseHandler.marshallCityObject(b3);
DatabaseHandler.marshallCityObject(b4);
assertEquals(4, DatabaseHandler.getFeatureCount());
handler.marshallCityObject(b);
handler.marshallCityObject(b2);
handler.marshallCityObject(b3);
handler.marshallCityObject(b4);
assertEquals(4, handler.getFeatureCount());
List<GmlId> objects = DatabaseHandler.getBBoxIntersectingObjects(b);
List<GmlId> objects = handler.getBBoxIntersectingObjects(b);
assertEquals(1, objects.size());
assertEquals(4, DatabaseHandler.getFeatureCount());
assertEquals(4, handler.getFeatureCount());
CityObject co = DatabaseHandler.unmarshallCityObject(objects.get(0));
CityObject co = handler.unmarshallCityObject(objects.get(0));
assertNotNull(co);
assertCityObjectEquality(b2, co);
......@@ -220,17 +217,17 @@ public class DataBaseHandlerTest {
geom3.updateEdgesAndVertices();
b3.addGeometry(geom3);
DatabaseHandler.marshallCityObject(b);
DatabaseHandler.marshallCityObject(b2);
DatabaseHandler.marshallCityObject(b3);
DatabaseHandler.marshallCityObject(b4);
assertEquals(4, DatabaseHandler.getFeatureCount());
handler.marshallCityObject(b);
handler.marshallCityObject(b2);
handler.marshallCityObject(b3);
handler.marshallCityObject(b4);
assertEquals(4, handler.getFeatureCount());
List<GmlId> objects = DatabaseHandler.getBufferIntersectingObjects(b, Math.sqrt(2));
List<GmlId> objects = handler.getBufferIntersectingObjects(b, Math.sqrt(2));
assertEquals(1, objects.size());
assertEquals(4, DatabaseHandler.getFeatureCount());
assertEquals(4, handler.getFeatureCount());
CityObject co = DatabaseHandler.unmarshallCityObject(objects.get(0));
CityObject co = handler.unmarshallCityObject(objects.get(0));
assertNotNull(co);
assertCityObjectEquality(b2, co);
......@@ -243,15 +240,15 @@ public class DataBaseHandlerTest {
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/SimpleSolid_SrefBS.gml", config);
Building b = model.getBuildings().get(0);
Building b = model.getBuildings().toList().get(0);
assertNotNull(b);
assertEquals(0, DatabaseHandler.getFeatureCount());
DatabaseHandler.marshallCityObject(b);
assertEquals(1, DatabaseHandler.getFeatureCount());
assertEquals(0, handler.getFeatureCount());
handler.marshallCityObject(b);
assertEquals(1, handler.getFeatureCount());
CityObject b2 = DatabaseHandler.unmarshallCityObject(b.getGmlId());
CityObject b2 = handler.unmarshallCityObject(b.getGmlId());
assertNotNull(b2);
assertEquals(1, DatabaseHandler.getFeatureCount());
assertEquals(1, handler.getFeatureCount());
assertCityObjectEquality(b, b2);
......@@ -268,15 +265,15 @@ public class DataBaseHandlerTest {
ParserConfiguration config = new ParserConfiguration(8, false);
CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/FZK_haus.gml", config);
Building b = model.getBuildings().get(0);
Building b = model.getBuildings().toList().get(0);
assertNotNull(b);
assertEquals(0, DatabaseHandler.getFeatureCount());
DatabaseHandler.marshallCityObject(b);
assertEquals(1, DatabaseHandler.getFeatureCount());
assertEquals(0, handler.getFeatureCount());
handler.marshallCityObject(b);
assertEquals(1, handler.getFeatureCount());
CityObject b2 = DatabaseHandler.unmarshallCityObject(b.getGmlId());
CityObject b2 = handler.unmarshallCityObject(b.getGmlId());
assertNotNull(b2);
assertEquals(1, DatabaseHandler.getFeatureCount());
assertEquals(1, handler.getFeatureCount());
assertCityObjectEquality(b, b2);
......
......@@ -5,40 +5,25 @@ import de.hft.stuttgart.citydoctor2.datastructure.GeometryTestUtils;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import org.citygml4j.core.model.building.AbstractBuilding;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
public class FeatureCacheTest {
@BeforeClass
public static void setUpBeforeClass() {
DatabaseHandler.setupDatabase();
}
@Before
public void resetDatabase() {
try {
DatabaseHandler.setupFeaturesTable();
} catch (Exception e) {
fail(e.getMessage());
}
}
@Test
public void testPut(){
FeatureCache cache = new FeatureCache("test");
Building b = new Building();
b.setGmlObject(mock(AbstractBuilding.class));
b.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.SOLID, Lod.LOD0));
assertEquals(0, DatabaseHandler.getFeatureCount());
FeatureCache cache = new FeatureCache();
assertEquals(0, cache.getFeatureCount());
cache.put(b);
assertEquals(1, DatabaseHandler.getFeatureCount());
assertEquals(1, cache.getFeatureCount());
}
......
......@@ -36,7 +36,7 @@ public class SerializationTest {
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().get(0);
Building b = model.getBuildings().toList().get(0);
assertNotNull(b);
Building b2 = SerializationUtils.roundtrip(b);
assertNotNull(b2);
......@@ -49,7 +49,7 @@ public class SerializationTest {
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().get(0);
Building b = model.getBuildings().toList().get(0);
assertNotNull(b);
Building b2 = SerializationUtils.roundtrip(b);
......
......@@ -147,7 +147,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());
}
......@@ -214,7 +214,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<CityObjectProperties> props = parsedBuilding.getGmlObject().getADEProperties(CityObjectProperties.class);
......@@ -271,7 +271,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
Building b = Mockito.mock(Building.class);
model.addBuilding(b);
assertEquals(b, model.getBuildings().get(0));
assertEquals(b, model.getBuildings().toList().get(0));
}
@Test
......@@ -281,7 +281,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
BridgeObject b = Mockito.mock(BridgeObject.class);
model.addBridge(b);
assertEquals(b, model.getBridges().get(0));
assertEquals(b, model.getBridges().toList().get(0));
}
@Test
......@@ -291,7 +291,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
Vegetation veg = Mockito.mock(Vegetation.class);
model.addVegetation(veg);
assertEquals(veg, model.getVegetation().get(0));
assertEquals(veg, model.getVegetation().toList().get(0));
}
@Test
......@@ -301,7 +301,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
Tunnel tunnel = Mockito.mock(Tunnel.class);
model.addTunnel(tunnel);
assertEquals(tunnel, model.getTunnels().get(0));
assertEquals(tunnel, model.getTunnels().toList().get(0));
}
......@@ -312,7 +312,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
TransportationObject trans = Mockito.mock(TransportationObject.class);
model.addTransportation(trans);
assertEquals(trans, model.getTransportation().get(0));
assertEquals(trans, model.getTransportation().toList().get(0));
}
......@@ -323,7 +323,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
LandObject land = Mockito.mock(LandObject.class);
model.addLand(land);
assertEquals(land, model.getLand().get(0));
assertEquals(land, model.getLand().toList().get(0));
}
@Test
......@@ -333,7 +333,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
WaterObject water = Mockito.mock(WaterObject.class);
model.addWater(water);
assertEquals(water, model.getWater().get(0));
assertEquals(water, model.getWater().toList().get(0));
}
@Test
......@@ -343,7 +343,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
CityFurniture cf = Mockito.mock(CityFurniture.class);
model.addCityFurniture(cf);
assertEquals(cf, model.getCityFurniture().get(0));
assertEquals(cf, model.getCityFurniture().toList().get(0));
}
@Test
......@@ -353,7 +353,7 @@ public class CityDoctorModelTest {
CityDoctorModel model = new CityDoctorModel(config, f);
GenericCityObject gen = Mockito.mock(GenericCityObject.class);
model.addGenericCityObject(gen);
assertEquals(gen, model.getGenericCityObjects().get(0));
assertEquals(gen, model.getGenericCityObjects().toList().get(0));
}
@Test
......@@ -402,10 +402,10 @@ public class CityDoctorModelTest {
Building b1 = Mockito.mock(Building.class);
Building b2 = Mockito.mock(Building.class);
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)
......@@ -426,10 +426,10 @@ public class CityDoctorModelTest {
BridgeObject b1 = Mockito.mock(BridgeObject.class);
BridgeObject b2 = Mockito.mock(BridgeObject.class);
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)
......@@ -450,10 +450,10 @@ public class CityDoctorModelTest {
Vegetation v1 = Mockito.mock(Vegetation.class);
Vegetation v2 = Mockito.mock(Vegetation.class);
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)
......@@ -474,10 +474,10 @@ public class CityDoctorModelTest {
Tunnel t1 = Mockito.mock(Tunnel.class);
Tunnel t2 = Mockito.mock(Tunnel.class);
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)
......@@ -498,10 +498,10 @@ public class CityDoctorModelTest {
TransportationObject t1 = Mockito.mock(TransportationObject.class);
TransportationObject t2 = Mockito.mock(TransportationObject.class);
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)
......@@ -522,10 +522,10 @@ public class CityDoctorModelTest {
LandObject lo1 = Mockito.mock(LandObject.class);
LandObject lo2 = Mockito.mock(LandObject.class);
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)
......@@ -546,10 +546,10 @@ public class CityDoctorModelTest {
WaterObject t1 = Mockito.mock(WaterObject.class);
WaterObject t2 = Mockito.mock(WaterObject.class);
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)
......@@ -570,10 +570,10 @@ public class CityDoctorModelTest {
CityFurniture cf1 = Mockito.mock(CityFurniture.class);
CityFurniture cf2 = Mockito.mock(CityFurniture.class);
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)
......@@ -594,10 +594,10 @@ public class CityDoctorModelTest {
GenericCityObject gco1 = Mockito.mock(GenericCityObject.class);
GenericCityObject gco2 = Mockito.mock(GenericCityObject.class);
model.addGenericCityObject(gco1);
assertEquals(gco1, model.getGenericCityObjects().get(0));
assertEquals(gco1, model.getGenericCityObjects().toList().get(0));
model.replaceFeature(gco1, gco2);
assertEquals(gco2, model.getGenericCityObjects().get(0));
assertEquals(1, model.getGenericCityObjects().size());
assertEquals(gco2, model.getGenericCityObjects().toList().get(0));
assertEquals(1, model.getGenericCityObjects().toList().size());
}
@Test(expected = IllegalStateException.class)
......
......@@ -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()) {
......
......@@ -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());
......
......@@ -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<Building> buildings = model.getBuildings();
List<Building> buildings = model.getBuildings().toList();
assertEquals(1, buildings.size());
Building building = buildings.get(0);
assertEquals("_Simple_BD.1", building.getGmlId().getGmlString());
......
......@@ -100,7 +100,7 @@ public class ZipTest {
cgmlArch.mountArchive(config);
CityDoctorModel mainModel = cgmlArch.getEntry("Main_model.gml").getModel();
assertEquals(18, mainModel.getGenericCityObjects().size());
assertEquals(18, mainModel.getGenericCityObjects().toList().size());
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment