Commit bd7cb123 authored by Riegel's avatar Riegel
Browse files

Feat: Add Embedded database implementation

parent e1dfa870
package de.hft.stuttgart.citydoctor2.database;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
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 org.h2gis.functions.factory.H2GISDBFactory;
import org.h2gis.utilities.wrapper.ConnectionWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DatabaseHandler {
private static final Logger logger = LogManager.getLogger(DatabaseHandler.class);
private static final String DB_NAME = "cd_db";
/**
* 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());
}
}
public static void setupFeaturesTable() {
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
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, type VARCHAR(255) NOT NULL)")) {
createPs.executeUpdate();
if (logger.isDebugEnabled()) {
logger.debug("Created features table");
}
}
} catch (SQLException e) {
logger.fatal("FATAL ERROR: Creation of CityDoctorModel database table failed!");
logger.fatal(e.getMessage());
}
}
public static void marshallCityObject(CityObject co) {
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("MERGE INTO features VALUES (?, ?, ?, ?)")) {
ps.setString(1, co.getGmlId().toString());
String bbox = BoundingBox.of(co.getHighestLodGeometry().getPolygons()).toWktShadow();
ps.setString(2, bbox);
if (logger.isDebugEnabled()) {
logger.debug("Attempting to serialize city object {} ", co);
}
ps.setString(4, co.getClass().getSimpleName());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bos)) {
out.writeObject(co);
}
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ps.setBinaryStream(3, bis, bytes.length);
ps.executeUpdate();
logger.debug("Successfully serialized CityObject to database");
}
} catch (SQLException e) {
logger.error("Saving of city object to embedded database failed!");
logger.debug(e.getMessage());
} catch (IOException e) {
logger.error("Encountered unknown writing error for embedded database!");
logger.debug(e.getMessage());
}
}
public static CityObject unmarshallCityObject(GmlId id) {
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM features WHERE gmlid = ?")) {
ps.setString(1, id.toString());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
try (InputStream is = rs.getBinaryStream("data")) {
return deserializeCityObject(new ObjectInputStream(is), rs.getString("type"));
}
}
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
logger.error("Loading of city object from embedded database failed!");
logger.debug(e.getMessage());
}
return null;
}
public static List<? extends CityObject> getBufferIntersectingObjects(CityObject co, Double buffersize) {
ResultSet rs = null;
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
} catch (SQLException e) {
logger.error("Connection to database failed while trying to get buffer intersecting objects!");
logger.debug(e.getMessage());
}
return Collections.emptyList();
}
public static List<CityObject> getBBoxIntersectingObjects(CityObject co) {
List<CityObject> intersectingObjects = new ArrayList<>();
try (Connection con = new ConnectionWrapper(H2GISDBFactory.openSpatialDataBase(DB_NAME))) {
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM features AS tab1" +
" WHERE ST_INTERSECTS(tab1.geom, (SELECT GEOM FROM features WHERE gmlid = ?)) AND tab1.gmlid <> ?")) {
ps.setString(1, co.getGmlId().toString());
ps.setString(2, co.getGmlId().toString());
ResultSet rs = ps.executeQuery();
intersectingObjects.addAll(retrieveCityObjects(rs));
}
} catch (SQLException e) {
logger.error("Connection to database failed while trying to get bbox intersecting objects!");
logger.debug(e.getMessage());
}
return intersectingObjects;
}
private static List<? extends CityObject> retrieveCityObjects(ResultSet rs) throws SQLException {
List<CityObject> cos = new ArrayList<>();
while (rs.next()) {
try (InputStream is = rs.getBinaryStream("data")) {
cos.add(deserializeCityObject(new ObjectInputStream(is), rs.getString("type")));
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return cos;
}
private static CityObject deserializeCityObject(ObjectInputStream ois, String className) throws IOException, ClassNotFoundException {
Class<?> type = Class.forName(className);
return (CityObject) type.cast(ois.readObject());
}
}
...@@ -251,6 +251,11 @@ ...@@ -251,6 +251,11 @@
<version>4.6.1</version> <version>4.6.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.orbisgis</groupId>
<artifactId>h2gis</artifactId>
<version>2.2.3</version>
</dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-controls</artifactId>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment