Skip to content
Snippets Groups Projects
Commit 4712d0c1 authored by Nikolaus Krismer's avatar Nikolaus Krismer
Browse files

changed method order

changed getAdjLinks method (a little)
parent e82f0e79
No related branches found
No related tags found
No related merge requests found
......@@ -65,6 +65,8 @@ public class Database<T extends ConfigDataset> {
protected boolean isIncoming;
protected Connection connection;
// Constructor
public Database(final T config, final Mode mode, final Direction direction) {
this.config = config;
this.isIncoming = (direction == Direction.INCOMING);
......@@ -73,212 +75,265 @@ public class Database<T extends ConfigDataset> {
connection = ConfigIsochrone.getInstance().getConnection();
pstmtsCacheMap = new HashMap<String, PreparedStatement>();
final String configDatecodes = config.getTableDatecodes();
final String configEdges = config.getTableEdges();
final String configSchedule = config.getTableSchedule();
final String configVertex = config.getTableVertex();
final String configVertexDensity = config.getTableVertexDensity();
queryLatestDepartureTimeHomo = "SELECT TIME_D, TIME_A, ROUTE_ID FROM ("
+ " SELECT TIME_D,TIME_A,ROUTE_ID FROM "
+ config.getTableSchedule()
+ configSchedule
+ " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_A>=? AND TIME_A<=? AND SERVICE_ID IN (%S)) C WHERE TIME_D >= ?";
queryEarliestArrivalTimeHomo = "SELECT TIME_D, TIME_A, ROUTE_ID FROM ("
+ " SELECT TIME_D, TIME_A, ROUTE_ID FROM "
+ config.getTableSchedule()
+ configSchedule
+ " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_D>=? AND TIME_D<=?"
+ " AND SERVICE_ID IN (%S)) C WHERE TIME_A <= ?";
queryGetAllEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + config.getTableEdges();
queryGetAllEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + configEdges;
queryGetContinuousEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + config.getTableEdges() + " WHERE EDGE_MODE=" + NW_MODE_CONTINUOUS;
queryGetContinuousEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + configEdges + " WHERE EDGE_MODE=" + NW_MODE_CONTINUOUS;
queryGetDateCodes = "SELECT DISTINCT SERVICE_ID "
+ " FROM "
+ config.getTableDaymarker()
+ configDatecodes
+ " WHERE (((MONDAY::int::bit || TUESDAY::int::bit || WEDNESDAY::int::bit || THURSDAY::int::bit"
+ " || FRIDAY::int::bit || SATURDAY::int::bit || SUNDAY::int::bit) & ?::bit(7))::int) > 0"
+ " AND START_DATE <= ? AND END_DATE >= ? "
+ " ORDER BY SERVICE_ID";
queryGetCoordinatesFromNode = "SELECT ID,ST_X(GEOMETRY) X, ST_Y(GEOMETRY) Y FROM " + config.getTableVertex() + " WHERE ID=?";
queryGetCoordinatesFromNode = "SELECT ID,ST_X(GEOMETRY) X, ST_Y(GEOMETRY) Y FROM " + configVertex + " WHERE ID=?";
queryGetRange = "select D0.DENSITY s0, D0.E_DISTANCE ed0, D1.DENSITY s1, D1.E_DISTANCE ed1 from "
+ "(SELECT ID,DENSITY,E_DISTANCE FROM "
+ config.getTableVertexDensity()
+ configVertexDensity
+ " WHERE ID=? AND DENSITY<? ORDER BY DENSITY DESC LIMIT 1) D0 FULL JOIN "
+ "(SELECT ID,DENSITY,E_DISTANCE FROM "
+ config.getTableVertexDensity()
+ configVertexDensity
+ " WHERE ID=? AND DENSITY>=? ORDER BY DENSITY ASC LIMIT 1) D1 ON D0.ID=D1.ID";
queryLoadLinksFromIER = "SELECT L.ID, L.SOURCE,L.SOURCE_MODE,L.TARGET,L.TARGET_MODE,L.LENGTH,L.EDGE_MODE,L.ROUTE_ID,"
+ (isIncoming ? "L.SOURCE_OUTDEGREE" : "L.TARGET_INDEGREE")
+ " DEGREE FROM " + config.getTableEdges() + " L, "
+ config.getTableVertex() + " N "
+ " DEGREE FROM " + configEdges + " L, "
+ configVertex + " N "
+ " WHERE L."
+ (isIncoming ? "TARGET" : "SOURCE")
+ "=N.ID" + " AND ST_DWITHIN(ST_PointFromText(?,?),N.GEOMETRY,?)='TRUE'";
queryGetLink = "SELECT SOURCE, TARGET, "
+ (isIncoming ? "SOURCE_OUTDEGREE" : "TARGET_INDEGREE")
+ " NODE_DEGREE, LENGTH FROM " + config.getTableEdges()
+ " NODE_DEGREE, LENGTH FROM " + configEdges
+ " WHERE ID = ? AND EDGE_MODE=" + NW_MODE_CONTINUOUS;
queryGetContinuousLink = "SELECT SOURCE, TARGET, "
+ (isIncoming ? "SOURCE_C_OUTDEGREE" : "TARGET_C_INDEGREE")
+ " NODE_DEGREE, LENGTH FROM " + config.getTableEdges()
+ " NODE_DEGREE, LENGTH FROM " + configEdges
+ " WHERE ID = ? AND EDGE_MODE=" + NW_MODE_CONTINUOUS;
queryGetContinuousNode = "SELECT "
+ (isIncoming ? "SOURCE_C_OUTDEGREE" : "TARGET_C_INDEGREE")
+ " NODE_DEGREE FROM " + config.getTableEdges()
+ " NODE_DEGREE FROM " + configEdges
+ (isIncoming ? "SOURCE=?" : "TARGET=?")
+ "AND EDGE_MODE=" + NW_MODE_CONTINUOUS;
queryGetMrneXNode = "SELECT "
+ (isIncoming ? "OUTDEGREE" : "INDEGREE")
+ " NODE_DEGREE, ST_X(GEOMETRY) X, ST_Y(GEOMETRY) Y FROM " + config.getTableVertex() + " WHERE ID=?";
+ " NODE_DEGREE, ST_X(GEOMETRY) X, ST_Y(GEOMETRY) Y FROM " + configVertex + " WHERE ID=?";
queryGetLinksInRange = "SELECT L.ID,L.SOURCE,L.SOURCE_MODE,L.TARGET,L.TARGET_MODE,L.LENGTH,L.EDGE_MODE,L.ROUTE_ID,"
+ (isIncoming ? "L.SOURCE_OUTDEGREE" : "L.TARGET_INDEGREE") + " DEGREE FROM " + config.getTableEdges()
+ " L, " + config.getTableVertex() + " N WHERE L." + (isIncoming ? "TARGET" : "SOURCE")
+ (isIncoming ? "L.SOURCE_OUTDEGREE" : "L.TARGET_INDEGREE") + " DEGREE FROM " + configEdges
+ " L, " + configVertex + " N WHERE L." + (isIncoming ? "TARGET" : "SOURCE")
+ "=N.ID AND st_intersects(N.GEOMETRY,%S)";
if (isIncoming) {
queryGetAdjLinks = "SELECT ID,SOURCE NODE_ID,SOURCE_OUTDEGREE NODE_DEGREE,LENGTH,EDGE_MODE,ROUTE_ID FROM " + config.getTableEdges() + " WHERE TARGET=?";
queryGetAdjContinuousLinks = "SELECT ID,SOURCE NODE_ID,SOURCE_C_OUTDEGREE NODE_DEGREE,LENGTH,EDGE_MODE,ROUTE_ID FROM " + config.getTableEdges()
+ " WHERE TARGET=? AND EDGE_MODE=" + NW_MODE_CONTINUOUS;
queryGetAdjLinks = "SELECT ID, SOURCE NODE_ID, SOURCE_OUTDEGREE NODE_DEGREE, LENGTH, EDGE_MODE, ROUTE_ID FROM "
+ configEdges + " WHERE TARGET=?";
queryGetAdjContinuousLinks = "SELECT ID, SOURCE NODE_ID, SOURCE_C_OUTDEGREE NODE_DEGREE, LENGTH, EDGE_MODE, ROUTE_ID FROM "
+ configEdges + " WHERE TARGET=? AND EDGE_MODE=" + NW_MODE_CONTINUOUS;
} else {
queryGetAdjLinks = "SELECT ID, TARGET NODE_ID, TARGET_INDEGREE NODE_DEGREE, LENGTH, EDGE_MODE, ROUTE_ID FROM "
+ configEdges + " WHERE SOURCE=?";
queryGetAdjContinuousLinks = "SELECT ID, TARGET NODE_ID, TARGET_C_INDEGREE NODE_DEGREE, LENGTH FROM "
+ configEdges + " WHERE TARGET=? AND EDGE_MODE=";
}
}
// Public methods
public void addLink(final Link link, final short degree, final Map<Integer, Node> nodes, final Map<Integer, List<Link>> adjList) {
int n1, n2;
if (isIncoming) {
n1 = link.getStartNode();
n2 = link.getEndNode();
} else {
queryGetAdjLinks = "SELECT ID,TARGET NODE_ID,TARGET_INDEGREE NODE_DEGREE, LENGTH,EDGE_MODE,ROUTE_ID FROM " + config.getTableEdges() + " WHERE SOURCE=?";
queryGetAdjContinuousLinks = "SELECT ID,TARGET NODE_ID, TARGET_C_INDEGREE NODE_DEGREE,LENGTH FROM " + config.getTableEdges() + " WHERE TARGET=? AND EDGE_MODE=";
n1 = link.getEndNode();
n2 = link.getStartNode();
}
addNode(n1, degree, nodes);
addNode(n2, nodes);
if (!adjList.containsKey(n2)) {
adjList.put(n2, new ArrayList<Link>());
}
adjList.get(n2).add(link);
}
/**
* Gets a prepared statement and caches it in a map. This
* is much more efficient than creating a new prepared statement
* each time a query needs to be called, and recalculating the
* queryplan each time.
* Closes all the open prepared statements and the database connection.
* This should be called once you're done with the database.
*/
public void close() {
for (final PreparedStatement pstmt : pstmtsCacheMap.values()) {
DbUtils.closeQuietly(pstmt);
}
}
/**
* Gets all links adjacent to a given node.
*
* @param query The prepared statement that is needed
* @return the cached prepared statement object
* @param nodeId the node to which the links should be adjacent
* @param nodes the nodes HashMap to which eventual new nodes should be added
* @return a list of links adjacent to the given nodeId
*/
// FIXME: Find a fix for prepared statements with parameters
// (we should NOT set strings in preparedStatemens just because we want to cache something)
protected PreparedStatement getPstmt(final String query) {
public Collection<Link> getAdjLinks(final int nodeId, final Map<Integer, Node> nodes) {
final PreparedStatement stmt = getPstmt((mode == Mode.UNIMODAL) ? queryGetAdjContinuousLinks : queryGetAdjLinks);
final Collection<Link> adjLinks = new ArrayList<Link>();
ResultSet rs = null;
try {
if (pstmtsCacheMap.containsKey(query) && !pstmtsCacheMap.get(query).isClosed()) {
return pstmtsCacheMap.get(query);
stmt.setInt(1, nodeId);
rs = stmt.executeQuery();
while (rs.next()) {
final int adjNodeId = rs.getInt("NODE_ID");
final short degree = rs.getShort("NODE_DEGREE");
addNode(adjNodeId, degree, nodes);
adjLinks.add(createLinkFromResultSet(nodeId, adjNodeId, rs));
}
final PreparedStatement pstmt = connection.prepareStatement(query);
pstmtsCacheMap.put(query, pstmt);
return pstmt;
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return null;
return adjLinks;
}
/**
* Reads the whole network for the MDijkstra Algorithm.
* The given maps have to be initialized and will be filled up with
* the nodes and links in the network.
* Gets the cost to go from one node to another node.
*
* @param nodes A map in which all the nodes should be stored.
* @param links A map in which all the links should be stored.
* @param node the node from which we should start calculating
* @param adjNode the node to which we want to calculate the cost
* @param routeIds the routeIds that should be taken into consideration
* @param dateCodes the days that should be taken into the account
* @param fromTime the earliest time for which we want to calculate the departure time
* @param toTime the latest time for which we want to calculate the departure time
* @return the cost of for traveling from the start node to the end node
*/
public void readNetwork(final Map<Integer, Node> nodes, final Map<Integer, Link> links) {
public double getAdjNodeCost(final Node node, final Node adjNode, final Set<Short> routeIds, final Set<Integer> dateCodes, final long fromTime, final long toTime) {
double minDistance = Double.POSITIVE_INFINITY;
ResultSet rs = null;
try {
PreparedStatement stmt;
if (mode == Mode.MULTIMODAL) {
stmt = getPstmt(queryGetAllEdges);
} else {
stmt = getPstmt(queryGetContinuousEdges);
}
rs = stmt.executeQuery();
while (rs.next()) {
final int linkId = rs.getInt("ID");
final int startNodeId = rs.getInt("SOURCE");
final int endNodeId = rs.getInt("TARGET");
final double length = rs.getDouble("LENGTH");
final short routeId = rs.getShort("ROUTE_ID");
final byte linkType = rs.getByte("EDGE_MODE");
int start, end;
if (isIncoming) {
start = startNodeId;
end = endNodeId;
} else {
start = endNodeId;
end = startNodeId;
}
Node node;
if (!nodes.containsKey(end)) {
node = new Node(end);
nodes.put(end, node);
} else {
node = nodes.get(end);
}
if (node.getAdjLinks() == null) {
node.setAdjLinks(new ArrayList<Link>());
}
Link link;
if (linkType == NW_MODE_CONTINUOUS) {
link = new Link(linkId, startNodeId, endNodeId, length);
} else {
link = new Link(linkId, startNodeId, endNodeId, routeId);
if (isIncoming) {
rs = getLatestDepartureTime(adjNode.getID(), node.getID(), routeIds, dateCodes, fromTime, Math.round(toTime - node.getDistance()));
while (rs.next()) {
final long departureTime = rs.getLong("TIME_D");
final long arrivalTime = rs.getLong("TIME_A");
final short routeId = rs.getShort("ROUTE_ID");
adjNode.setDepartureTime(routeId, departureTime);
node.setArrivalTime(routeId, arrivalTime);
final double distance = toTime - departureTime;
if (distance < minDistance) {
minDistance = distance;
adjNode.setCheapestReachedRouteId(routeId);
}
}
node.addAdjLink(link);
links.put(linkId, link);
if (!nodes.containsKey(start)) {
nodes.put(start, new Node(start));
} else {
rs = getEarliestArrivalTime(node.getID(), adjNode.getID(), routeIds, dateCodes, Math.round(fromTime + node.getDistance()), toTime);
while (rs.next()) {
final long departureTime = rs.getLong("TIME_D");
final long arrivalTime = rs.getLong("TIME_A");
final short routeId = rs.getShort("ROUTE_ID");
adjNode.setArrivalTime(routeId, arrivalTime);
node.setDepartureTime(routeId, departureTime);
final double distance = arrivalTime > 0 ? arrivalTime - fromTime : Double.POSITIVE_INFINITY;
if (distance < minDistance) {
minDistance = distance;
adjNode.setCheapestReachedRouteId(routeId);
}
}
}
} catch (final SQLException e) {
throw new RuntimeException("Error reading the Network: " + e);
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return minDistance;
}
/**
* Prepares a number of place holders for a prepared statement.
* Gets the coordinates of a node.
*
* @param length The number of placeholders that is needed
* @return a string with the placeholders plugged in to a
* statement.
* @param nodeId the nodeId of the node for which we should find the coordinates
* @return a point with the coordinates of the node
*/
protected final String preparePlaceHolders(final int length) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; ++i) {
builder.append("?");
if ((i + 1) < length) {
builder.append(",");
public Point getCoordinates(final int nodeId) {
final PreparedStatement stmt = getPstmt(queryGetCoordinatesFromNode);
Point gp = null;
ResultSet rs = null;
try {
stmt.setInt(1, nodeId);
rs = stmt.executeQuery();
if (rs.next()) {
gp = new Point(rs.getDouble("X"), rs.getDouble("Y"));
}
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return builder.toString();
return gp;
}
/**
* Sets the values in the placeholders in a prepared statement, generated by
* the {@link #preparePlaceHolders(int)} method.
* Gets date codes for a given time.
*
* @see #preparePlaceHolders(int)
* @param startIdx the start index where the first object should be placed in the prepared statement
* @param preparedStatement the prepared statement in which the values should be inserted.
* @param values the values that should be inserted into the prepared statement
* @throws SQLException thrown if a parameter could not be set into the prepared statement
* @return the index of the first position that was being left unfilled by the method
* @param time the given
* @return returns a set of date codes
*/
protected final int setValues(final int startIdx, final PreparedStatement preparedStatement, final Object... values) throws SQLException {
for (int i = 0; i < values.length; ++i) {
preparedStatement.setObject(startIdx + i, values[i]);
public Set<Integer> getDateCodes(final Calendar time) {
final PreparedStatement stmt = getPstmt(queryGetDateCodes);
final Set<Integer> codes = new HashSet<Integer>();
ResultSet rs = null;
try {
final Date date = new Date(time.getTimeInMillis());
// CHECKSTYLE:OFF MagicNumber
stmt.setString(1, getWeekDayMask(time));
stmt.setDate(2, date);
stmt.setDate(3, date);
// CHECKSTYLE:ON MagicNumber
rs = stmt.executeQuery();
while (rs.next()) {
codes.add(rs.getInt("SERVICE_ID"));
}
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return startIdx + values.length;
return codes;
}
/**
* Gets the latest departure time to start from source, to arrive at the target in time.
* Gets the earliest arrival time at the target when traveled from the source.
*
* @param sourceId the id of the source node
* @param targetId the id of the target node
......@@ -289,8 +344,8 @@ public class Database<T extends ConfigDataset> {
* @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
* @return a resultSet with all the times that come into consideration
*/
public ResultSet getLatestDepartureTime(final int sourceId, final int targetId, final Set<Short> routeIds, final Set<Integer> dateCodes, final long from, final long to) throws SQLException {
final String sql = String.format(queryLatestDepartureTimeHomo, preparePlaceHolders(routeIds.size()), preparePlaceHolders(dateCodes.size()));
public ResultSet getEarliestArrivalTime(final int sourceId, final int targetId, final Set<Short> routeIds, final Set<Integer> dateCodes, final long from, final long to) throws SQLException {
final String sql = String.format(queryEarliestArrivalTimeHomo, preparePlaceHolders(routeIds.size()), preparePlaceHolders(dateCodes.size()));
final PreparedStatement statement = getPstmt(sql);
// CHECKSTYLE:OFF MagicNumber
......@@ -300,14 +355,14 @@ public class Database<T extends ConfigDataset> {
statement.setLong(idx++, from);
statement.setLong(idx++, to);
idx = setValues(idx, statement, dateCodes.toArray());
statement.setLong(idx, from);
statement.setLong(idx, to);
// CHECKSTYLE:ON MagicNumber
return statement.executeQuery();
}
/**
* Gets the earliest arrival time at the target when traveled from the source.
* Gets the latest departure time to start from source, to arrive at the target in time.
*
* @param sourceId the id of the source node
* @param targetId the id of the target node
......@@ -318,8 +373,8 @@ public class Database<T extends ConfigDataset> {
* @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
* @return a resultSet with all the times that come into consideration
*/
public ResultSet getEarliestArrivalTime(final int sourceId, final int targetId, final Set<Short> routeIds, final Set<Integer> dateCodes, final long from, final long to) throws SQLException {
final String sql = String.format(queryEarliestArrivalTimeHomo, preparePlaceHolders(routeIds.size()), preparePlaceHolders(dateCodes.size()));
public ResultSet getLatestDepartureTime(final int sourceId, final int targetId, final Set<Short> routeIds, final Set<Integer> dateCodes, final long from, final long to) throws SQLException {
final String sql = String.format(queryLatestDepartureTimeHomo, preparePlaceHolders(routeIds.size()), preparePlaceHolders(dateCodes.size()));
final PreparedStatement statement = getPstmt(sql);
// CHECKSTYLE:OFF MagicNumber
......@@ -329,117 +384,26 @@ public class Database<T extends ConfigDataset> {
statement.setLong(idx++, from);
statement.setLong(idx++, to);
idx = setValues(idx, statement, dateCodes.toArray());
statement.setLong(idx, to);
statement.setLong(idx, from);
// CHECKSTYLE:ON MagicNumber
return statement.executeQuery();
}
/**
* Gets the cost to go from one node to another node.
* Get a single link from the network and and add the source
* node to the nodes table if necessary.
*
* @param node the node from which we should start calculating
* @param adjNode the node to which we want to calculate the cost
* @param routeIds the routeIds that should be taken into consideration
* @param dateCodes the days that should be taken into the account
* @param fromTime the earliest time for which we want to calculate the departure time
* @param toTime the latest time for which we want to calculate the departure time
* @return the cost of for traveling from the start node to the end node
* @param linkId the id of the link that should be returned
* @param nodes the nodes table to which the node should be added (can only be null if the link is needed)
* @return the link with id linkId
*/
public double getAdjNodeCost(final Node node, final Node adjNode, final Set<Short> routeIds, final Set<Integer> dateCodes, final long fromTime, final long toTime) {
double minDistance = Double.POSITIVE_INFINITY;
public Link getLink(final int linkId, final Map<Integer, Node> nodes) {
final PreparedStatement stmt = getPstmt((mode == Mode.UNIMODAL) ? queryGetContinuousLink : queryGetLink);
Link link = null;
ResultSet rs = null;
try {
if (isIncoming) {
rs = getLatestDepartureTime(adjNode.getID(), node.getID(), routeIds, dateCodes, fromTime, Math.round(toTime - node.getDistance()));
while (rs.next()) {
final long departureTime = rs.getLong("TIME_D");
final long arrivalTime = rs.getLong("TIME_A");
final short routeId = rs.getShort("ROUTE_ID");
adjNode.setDepartureTime(routeId, departureTime);
node.setArrivalTime(routeId, arrivalTime);
final double distance = toTime - departureTime;
if (distance < minDistance) {
minDistance = distance;
adjNode.setCheapestReachedRouteId(routeId);
}
}
} else {
rs = getEarliestArrivalTime(node.getID(), adjNode.getID(), routeIds, dateCodes, Math.round(fromTime + node.getDistance()), toTime);
while (rs.next()) {
final long departureTime = rs.getLong("TIME_D");
final long arrivalTime = rs.getLong("TIME_A");
final short routeId = rs.getShort("ROUTE_ID");
adjNode.setArrivalTime(routeId, arrivalTime);
node.setDepartureTime(routeId, departureTime);
final double distance = arrivalTime > 0 ? arrivalTime - fromTime : Double.POSITIVE_INFINITY;
if (distance < minDistance) {
minDistance = distance;
adjNode.setCheapestReachedRouteId(routeId);
}
}
}
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return minDistance;
}
/**
* Adds a node to the network.
*
* @param nodeId The nodeId of the node that should be added
* @param nrAdjLinks The number of links adjacent to the node
* @param nodes The nodes HashMap to which the node should be added
*/
private void addNode(final int nodeId, final short nrAdjLinks, final Map<Integer, Node> nodes) {
if (nodes == null) {
return; // Just for safety
}
final Node node = nodes.get(nodeId);
if (node == null) {
nodes.put(nodeId, new Node(nodeId, nrAdjLinks));
} else if (node.getNrAdjacentLinks() == -1) {
node.setNrAdjacentLinks(nrAdjLinks);
}
}
/**
* Adds a node to the network.
*
* @param nodeId The nodeId of the node that should be added
* @param nodes The HashMap to which the node should be added
*/
private void addNode(final int nodeId, final Map<Integer, Node> nodes) {
if (nodes != null && !nodes.containsKey(nodeId)) {
nodes.put(nodeId, new Node(nodeId));
}
}
/**
* Get a single link from the network and and add the source
* node to the nodes table if necessary.
*
* @param linkId The id of the link that should be returned
* @param nodes The nodes table to which the node should be
* added. Can be null if only the link is needed.
* @return The link with id linkId
*/
public Link getLink(final int linkId, final Map<Integer, Node> nodes) {
Link link = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
if (mode == Mode.UNIMODAL) {
stmt = getPstmt(queryGetContinuousLink);
} else {
stmt = getPstmt(queryGetLink);
}
stmt.setInt(1, linkId);
rs = stmt.executeQuery();
if (rs.next()) {
......@@ -447,12 +411,13 @@ public class Database<T extends ConfigDataset> {
final int targetId = rs.getInt("TARGET");
final short degree = rs.getShort("NODE_DEGREE");
final double length = rs.getDouble("LENGTH");
link = new Link(linkId, sourceId, targetId, length);
if (isIncoming) {
addNode(sourceId, degree, nodes);
} else {
addNode(targetId, degree, nodes);
}
link = new Link(linkId, sourceId, targetId, length);
}
} catch (final SQLException e) {
e.printStackTrace();
......@@ -466,21 +431,15 @@ public class Database<T extends ConfigDataset> {
/**
* Gets a node from the database.
*
* @param nodeId The id of the node that should be read from
* the database.
* @param nodeId the id of the node that should be read from the database
* @return the node from the database
*/
public Node getNode(final int nodeId) {
final PreparedStatement stmt = getPstmt((mode == Mode.UNIMODAL) ? queryGetContinuousNode : queryGetMrneXNode);
Node node = null;
ResultSet rs = null;
try {
PreparedStatement stmt;
if (mode == Mode.UNIMODAL) {
stmt = getPstmt(queryGetContinuousNode);
} else {
stmt = getPstmt(queryGetMrneXNode);
}
stmt.setInt(1, nodeId);
rs = stmt.executeQuery();
if (rs.next()) {
......@@ -499,163 +458,160 @@ public class Database<T extends ConfigDataset> {
}
/**
* Gets all links adjacent to a given node.
* Returns the maximal range for the given vertex with a maximal number of specified vertices.
* The database query used finds the last two tuples having a memory size smaller than the specified memorySize and then interpolates the range.
*
* @param nodeId The node to which the links should be
* adjacent.
* @param nodes The nodes HashMap to which eventual new nodes
* should be added.
* @return a list of links adjacent to the given nodeid
* @param nodeId the vertex identifier
* @param memorySize the maximal number of vertices
* @return the available range as the euclidean distance
*/
public Collection<Link> getAdjLinks(final int nodeId, final Map<Integer, Node> nodes) {
final Collection<Link> adjLinks = new ArrayList<Link>();
public double getRange(final int nodeId, final int memorySize) {
final PreparedStatement stmt = getPstmt(queryGetRange);
ResultSet rs = null;
PreparedStatement stmt = null;
try {
if (mode == Mode.UNIMODAL) {
stmt = getPstmt(queryGetAdjContinuousLinks);
} else {
stmt = getPstmt(queryGetAdjLinks);
}
// CHECKSTYLE:OFF MagicNumber
stmt.setInt(1, nodeId);
stmt.setInt(2, memorySize);
stmt.setInt(3, nodeId);
stmt.setInt(4, memorySize);
// CHECKSTYLE:ON MagicNumber
rs = stmt.executeQuery();
while (rs.next()) {
Link link;
final int linkId = rs.getInt("ID");
final byte linkType = rs.getByte("EDGE_MODE");
final int adjNodeId = rs.getInt("NODE_ID");
final short degree = rs.getShort("NODE_DEGREE");
final double length = rs.getDouble("LENGTH");
final short routeId = rs.getShort("ROUTE_ID");
int start, end;
if (isIncoming) {
start = adjNodeId;
end = nodeId;
} else {
start = nodeId;
end = adjNodeId;
}
if (linkType == NW_MODE_CONTINUOUS) {
link = new Link(linkId, start, end, length);
} else {
link = new Link(linkId, start, end, routeId);
}
addNode(adjNodeId, degree, nodes);
adjLinks.add(link);
int s0 = 0, s1 = 0;
double ed0 = 0, ed1 = 0;
if (rs.next()) {
s0 = rs.getInt("s0");
ed0 = rs.getDouble("ed0");
s1 = rs.getInt("s1");
ed1 = rs.getDouble("ed1");
}
return ed0 + (ed1 - ed0) / (s1 - s0) * (memorySize - s0);
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return adjLinks;
return 0;
}
/**
* Gets date codes for a given time.
*
* @param time the given
* @return returns a set of date codes
* Loads the links in a circle from the database (for better explanation see the MrneX algorithm).
*/
public Set<Integer> getDateCodes(final Calendar time) {
final Set<Integer> codes = new HashSet<Integer>();
final PreparedStatement stmt = getPstmt(queryGetDateCodes);
public void loadLinksFromIER(final Node node, final Collection<Node> intersections, final Map<Integer, Node> nodes, final Map<Integer, List<Link>> adjList) {
PreparedStatement stmt = null;
ResultSet rs = null;
final Point g = node.getCoordinates();
final String pointString = "POINT( " + g.getX() + " " + g.getY() + ")";
try {
final Date date = new Date(time.getTimeInMillis());
// CHECKSTYLE:OFF MagicNumber
stmt.setString(1, getWeekDayMask(time));
stmt.setDate(2, date);
stmt.setDate(3, date);
// CHECKSTYLE:ON MagicNumber
if (intersections.isEmpty()) {
stmt = getPstmt(queryLoadLinksFromIER);
// CHECKSTYLE:OFF MagicNumber
stmt.setString(1, pointString);
stmt.setInt(2, config.getServerSRID());
stmt.setDouble(3, node.getRadius());
// CHECKSTYLE:ON MagicNumber
} else {
final Node[] loadedAreas = intersections.toArray(new Node[0]);
final String disjunctAreaString = "st_difference(st_buffer(st_pointfromtext('" + pointString + "',"
+ config.getServerSRID() + ")," + node.getRadius() + ")," + subQuery(loadedAreas, loadedAreas.length - 1, config.getServerSRID()) + ")";
stmt = getPstmt(String.format(queryGetLinksInRange, disjunctAreaString));
}
rs = stmt.executeQuery();
while (rs.next()) {
codes.add(rs.getInt("SERVICE_ID"));
final int linkId = rs.getInt("ID");
final int sourceId = rs.getInt("SOURCE");
final short degree = rs.getShort("DEGREE");
final int targetId = rs.getInt("TARGET");
final byte edgeMode = rs.getByte("EDGE_MODE");
Link l = null;
if (edgeMode == NW_MODE_CONTINUOUS) {
final double length = rs.getDouble("LENGTH");
l = new Link(linkId, sourceId, targetId, length);
} else {
final short routeId = rs.getShort("ROUTE_ID");
l = new Link(linkId, sourceId, targetId, routeId);
}
addLink(l, degree, nodes, adjList);
}
} catch (final SQLException e) {
System.err.println("Problems with node:" + node);
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return codes;
}
/**
* Transforms the day into something machine-readable.
* Reads the whole network for the MDijkstra Algorithm.
* The given maps have to be initialized and will be filled up with
* the nodes and links in the network.
*
* @param time the calendar object to get the machine-readable week day from
* @return the machine-readable string (binary form)
* @param nodes A map in which all the nodes should be stored.
* @param links A map in which all the links should be stored.
*/
private String getWeekDayMask(final Calendar time) {
switch (time.get(Calendar.DAY_OF_WEEK)) {
case Calendar.MONDAY:
return "1000000";
case Calendar.TUESDAY:
return "0100000";
case Calendar.WEDNESDAY:
return "0010000";
case Calendar.THURSDAY:
return "0001000";
case Calendar.FRIDAY:
return "0000100";
case Calendar.SATURDAY:
return "0000010";
case Calendar.SUNDAY:
return "0000001";
default:
return "1000000";
}
}
public void readNetwork(final Map<Integer, Node> nodes, final Map<Integer, Link> links) {
final PreparedStatement stmt = getPstmt((mode == Mode.UNIMODAL) ? queryGetContinuousEdges : queryGetAllEdges);
/**
* Gets the coordinates of a node.
*
* @param nodeId The nodeId of the node for which we should
* find the coordinates.
* @return a point with the coordinates of the node
*/
public Point getCoordinates(final int nodeId) {
Point gp = null;
ResultSet rs = null;
try {
final PreparedStatement stmt = getPstmt(queryGetCoordinatesFromNode);
stmt.setInt(1, nodeId);
rs = stmt.executeQuery();
if (rs.next()) {
gp = new Point(rs.getDouble("X"), rs.getDouble("Y"));
while (rs.next()) {
final int linkId = rs.getInt("ID");
final int startNodeId = rs.getInt("SOURCE");
final int endNodeId = rs.getInt("TARGET");
final double length = rs.getDouble("LENGTH");
final short routeId = rs.getShort("ROUTE_ID");
final byte linkType = rs.getByte("EDGE_MODE");
int start, end;
if (isIncoming) {
start = startNodeId;
end = endNodeId;
} else {
start = endNodeId;
end = startNodeId;
}
Node node;
if (!nodes.containsKey(end)) {
node = new Node(end);
nodes.put(end, node);
} else {
node = nodes.get(end);
}
if (node.getAdjLinks() == null) {
node.setAdjLinks(new ArrayList<Link>());
}
Link link;
if (linkType == NW_MODE_CONTINUOUS) {
link = new Link(linkId, startNodeId, endNodeId, length);
} else {
link = new Link(linkId, startNodeId, endNodeId, routeId);
}
node.addAdjLink(link);
links.put(linkId, link);
if (!nodes.containsKey(start)) {
nodes.put(start, new Node(start));
}
}
} catch (final SQLException e) {
e.printStackTrace();
throw new RuntimeException("Error reading the Network: " + e);
} finally {
DbUtils.closeQuietly(rs);
}
return gp;
}
/**
* Close all the open prepared statements and the database
* connection. Call this method once you're done with the
* database.
*/
public void close() {
for (final PreparedStatement pstmt : pstmtsCacheMap.values()) {
DbUtils.closeQuietly(pstmt);
}
}
/**
* If close() is not called, make sure the database connections
* If {@link #close()} is not called, make sure the database connections
* are still closed. This method is just a security guard and
* should not be relied on and is not an excuse for a lazy
* programmer not to call the close method.
* This method is not guaranteed to be called!!
*
* @see #close()
* @throws Throwable the {@code Exception} raised by this method
*/
@Override
......@@ -664,121 +620,163 @@ public class Database<T extends ConfigDataset> {
close();
}
// Protected methods
/**
* Method getRange returns the maximal range for the given
* vertex with a maximal number of specified vertices. Query
* find the last two tuples having a memory size smaller than
* memorySize and then interpolates the range.
* Gets a prepared statement and caches it in a map. This
* is much more efficient than creating a new prepared statement
* each time a query needs to be called, and recalculating the
* queryplan each time.
*
* @param nodeId the vertex identifier
* @param memorySize the maximal number of vertices
* @return the available range as the euclidean distance
* @param query The prepared statement that is needed
* @return the cached prepared statement object
*/
public double getRange(final int nodeId, final int memorySize) {
ResultSet rs = null;
// FIXME: Find a fix for prepared statements with parameters
// (we should NOT set strings in preparedStatemens just because we want to cache something)
protected PreparedStatement getPstmt(final String query) {
try {
final PreparedStatement stmt = getPstmt(queryGetRange);
// CHECKSTYLE:OFF MagicNumber
stmt.setInt(1, nodeId);
stmt.setInt(2, memorySize);
stmt.setInt(3, nodeId);
stmt.setInt(4, memorySize);
// CHECKSTYLE:ON MagicNumber
rs = stmt.executeQuery();
int s0 = 0, s1 = 0;
double ed0 = 0, ed1 = 0;
if (rs.next()) {
s0 = rs.getInt("s0");
ed0 = rs.getDouble("ed0");
s1 = rs.getInt("s1");
ed1 = rs.getDouble("ed1");
if (pstmtsCacheMap.containsKey(query) && !pstmtsCacheMap.get(query).isClosed()) {
return pstmtsCacheMap.get(query);
}
return ed0 + (ed1 - ed0) / (s1 - s0) * (memorySize - s0);
final PreparedStatement pstmt = connection.prepareStatement(query);
pstmtsCacheMap.put(query, pstmt);
return pstmt;
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
}
return 0;
return null;
}
public void addLink(final Link link, final short degree, final Map<Integer, Node> nodes, final Map<Integer, List<Link>> adjList) {
int n1, n2;
// Private methods
private Link createLinkFromResultSet(final int nodeId, final int adjNodeId, final ResultSet rs) throws SQLException {
int start, end;
if (isIncoming) {
n1 = link.getStartNode();
n2 = link.getEndNode();
start = adjNodeId;
end = nodeId;
} else {
n1 = link.getEndNode();
n2 = link.getStartNode();
start = nodeId;
end = adjNodeId;
}
addNode(n1, degree, nodes);
addNode(n2, nodes);
if (!adjList.containsKey(n2)) {
adjList.put(n2, new ArrayList<Link>());
final int linkId = rs.getInt("ID");
if (rs.getByte("EDGE_MODE") == NW_MODE_CONTINUOUS) {
final double length = rs.getDouble("LENGTH");
return new Link(linkId, start, end, length);
}
adjList.get(n2).add(link);
final short routeId = rs.getShort("ROUTE_ID");
return new Link(linkId, start, end, routeId);
}
private String subQuery(final Node[] loaded, final int idx, final int srid) {
if (idx == 0) {
return "st_buffer(st_pointfromtext('POINT(" + loaded[idx].getCoordinates().getX() + " "
+ loaded[idx].getCoordinates().getY() + ")'," + srid + ")," + loaded[idx].getRadius() + ")";
} else {
return "st_union(" + "st_buffer(st_pointfromtext('POINT(" + loaded[idx].getCoordinates().getX() + " "
+ loaded[idx].getCoordinates().getY() + ")'," + srid + ")," + loaded[idx].getRadius() + "),"
+ subQuery(loaded, idx - 1, srid) + ")";
// Private static methods
/**
* Prepares a number of place holders for a prepared statement.
*
* @param length The number of placeholders that is needed
* @return a string with the placeholders plugged in to a statement.
*/
private static String preparePlaceHolders(final int length) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; ++i) {
builder.append("?");
if ((i + 1) < length) {
builder.append(",");
}
}
return builder.toString();
}
/**
* Loads the links in a circle from the database (for better explanation see the MrneX algorithm).
* Sets the values in the placeholders in a prepared statement, generated by
* the {@link #preparePlaceHolders(int)} method.
*
* @see #preparePlaceHolders(int)
* @param startIdx the start index where the first object should be placed in the prepared statement
* @param preparedStatement the prepared statement in which the values should be inserted.
* @param values the values that should be inserted into the prepared statement
* @throws SQLException thrown if a parameter could not be set into the prepared statement
* @return the index of the first position that was being left unfilled by the method
*/
public void loadLinksFromIER(final Node node, final Collection<Node> intersections, final Map<Integer, Node> nodes, final Map<Integer, List<Link>> adjList) {
ResultSet rs = null;
protected static final int setValues(final int startIdx, final PreparedStatement preparedStatement, final Object... values) throws SQLException {
for (int i = 0; i < values.length; ++i) {
preparedStatement.setObject(startIdx + i, values[i]);
}
final Point g = node.getCoordinates();
final String pointString = "POINT( " + g.getX() + " " + g.getY() + ")";
try {
PreparedStatement stmt = null;
if (intersections.isEmpty()) {
stmt = getPstmt(queryLoadLinksFromIER);
// CHECKSTYLE:OFF MagicNumber
stmt.setString(1, pointString);
stmt.setInt(2, config.getServerSRID());
stmt.setDouble(3, node.getRadius());
// CHECKSTYLE:ON MagicNumber
} else {
final Node[] loadedAreas = intersections.toArray(new Node[0]);
final String disjunctAreaString = "st_difference(st_buffer(st_pointfromtext('" + pointString + "',"
+ config.getServerSRID() + ")," + node.getRadius() + ")," + subQuery(loadedAreas, loadedAreas.length - 1, config.getServerSRID()) + ")";
stmt = getPstmt(String.format(queryGetLinksInRange, disjunctAreaString));
}
rs = stmt.executeQuery();
return startIdx + values.length;
}
while (rs.next()) {
final int linkId = rs.getInt("ID");
final int sourceId = rs.getInt("SOURCE");
final short degree = rs.getShort("DEGREE");
final int targetId = rs.getInt("TARGET");
final byte edgeMode = rs.getByte("EDGE_MODE");
Link l = null;
if (edgeMode == NW_MODE_CONTINUOUS) {
final double length = rs.getDouble("LENGTH");
l = new Link(linkId, sourceId, targetId, length);
} else {
final short routeId = rs.getShort("ROUTE_ID");
l = new Link(linkId, sourceId, targetId, routeId);
}
addLink(l, degree, nodes, adjList);
}
} catch (final SQLException e) {
System.err.println("Problems with node:" + node);
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
/**
* Adds a node to the network.
*
* @param nodeId The nodeId of the node that should be added
* @param nodes The HashMap to which the node should be added
*/
private static void addNode(final int nodeId, final Map<Integer, Node> nodes) {
if (nodes != null && !nodes.containsKey(nodeId)) {
nodes.put(nodeId, new Node(nodeId));
}
}
/**
* Adds a node to the network.
*
* @param nodeId The nodeId of the node that should be added
* @param nrAdjLinks The number of links adjacent to the node
* @param nodes The nodes HashMap to which the node should be added
*/
private static void addNode(final int nodeId, final short nrAdjLinks, final Map<Integer, Node> nodes) {
if (nodes == null) {
return; // Just for safety
}
final Node node = nodes.get(nodeId);
if (node == null) {
nodes.put(nodeId, new Node(nodeId, nrAdjLinks));
} else if (node.getNrAdjacentLinks() == -1) {
node.setNrAdjacentLinks(nrAdjLinks);
}
}
/**
* Transforms the day into something machine-readable.
*
* @param time the calendar object to get the machine-readable week day from
* @return the machine-readable string (binary form)
*/
private static String getWeekDayMask(final Calendar time) {
switch (time.get(Calendar.DAY_OF_WEEK)) {
case Calendar.MONDAY:
return "1000000";
case Calendar.TUESDAY:
return "0100000";
case Calendar.WEDNESDAY:
return "0010000";
case Calendar.THURSDAY:
return "0001000";
case Calendar.FRIDAY:
return "0000100";
case Calendar.SATURDAY:
return "0000010";
case Calendar.SUNDAY:
return "0000001";
default:
return "1000000";
}
}
private static String subQuery(final Node[] loaded, final int idx, final int srid) {
if (idx == 0) {
return "st_buffer(st_pointfromtext('POINT(" + loaded[idx].getCoordinates().getX() + " "
+ loaded[idx].getCoordinates().getY() + ")'," + srid + ")," + loaded[idx].getRadius() + ")";
} else {
return "st_union(" + "st_buffer(st_pointfromtext('POINT(" + loaded[idx].getCoordinates().getX() + " "
+ loaded[idx].getCoordinates().getY() + ")'," + srid + ")," + loaded[idx].getRadius() + "),"
+ subQuery(loaded, idx - 1, srid) + ")";
}
}
}
......@@ -49,12 +49,14 @@ public class DatabaseWeb extends Database<ConfigClient> {
private final String queryInsertVertexAnnotation;
private final String queryUpdateVertices;
// Constructor
public DatabaseWeb(final ConfigClient config, final Mode mode, final Direction direction) {
super(config, mode, direction);
final String cfgEdges = config.getTableEdges();
final String cfgRoutes = config.getTableRoutes();
final String cfgVertex = config.getTableVertex();
final String configEdges = config.getTableEdges();
final String configRoutes = config.getTableRoutes();
final String configVertex = config.getTableVertex();
final String edgeTableName = config.getEdgeTableEntry().getTableName();
final String vertexTableName = config.getVertexTableEntry().getTableName();
final String vertexAnnotationTableName = config.getVertexAnnotatedTableEntry().getTableName();
......@@ -65,41 +67,33 @@ public class DatabaseWeb extends Database<ConfigClient> {
queryStoreLinks = "INSERT INTO " + edgeTableName
+ " (\"ID\",\"SOURCE\",\"TARGET\",\"OFFSET\",\"LENGTH\",\"GEOMETRY\") (SELECT ID, SOURCE, TARGET, ?, LENGTH,"
+ " GEOMETRY FROM " + cfgEdges + " WHERE ID=?)";
+ " GEOMETRY FROM " + configEdges + " WHERE ID=?)";
queryStorePartialLinks = "INSERT INTO " + edgeTableName
+ " (\"ID\",\"SOURCE\",\"TARGET\",\"OFFSET\",\"LENGTH\",\"GEOMETRY\") (SELECT ID,SOURCE,TARGET,?,LENGTH,"
+ " ST_LINE_SUBSTRING(GEOMETRY,?,?) FROM " + cfgEdges + " WHERE ID = ?)";
+ " ST_LINE_SUBSTRING(GEOMETRY,?,?) FROM " + configEdges + " WHERE ID = ?)";
queryInsertVertex = "INSERT INTO " + vertexTableName
+ " (\"ID\",\"DISTANCE\",\"ROUTE_ID\",\"STATE\",\"GEOMETRY\") (SELECT ?,?,?,?,GEOMETRY FROM " + cfgVertex
+ " (\"ID\",\"DISTANCE\",\"ROUTE_ID\",\"STATE\",\"GEOMETRY\") (SELECT ?,?,?,?,GEOMETRY FROM " + configVertex
+ " WHERE ID=?)";
queryInsertVertexAnnotation = "INSERT INTO " + vertexAnnotationTableName
+ " (\"ID\", \"ROUTE_ID\",\"TIME_A\",\"TIME_D\") VALUES (?,?,?,?)";
queryUpdateVertices = "UPDATE " + vertexTableName
+ " SET \"T_TYPE\"=R.ROUTE_TYPE FROM " + cfgRoutes + " R WHERE R.ROUTE_ID = "
+ " SET \"T_TYPE\"=R.ROUTE_TYPE FROM " + configRoutes + " R WHERE R.ROUTE_ID = "
+ vertexTableName + ".\"ROUTE_ID\" AND " + vertexTableName + ".\"ROUTE_ID\">=0";
}
public Point transform(final Point p) {
final String query = "SELECT ST_X(P.GEO) X, ST_Y(P.GEO) Y FROM (SELECT ST_Transform(ST_PointFromText(?,?),?) GEO ) P";
return DatabaseWeb.transform(config, p, getPstmt(query));
}
public Connection getConnection() {
return connection;
}
// Public methods
public void createBuffer(final String bufferTable, final String edgeTable, final double bufferSize) {
final String query = "INSERT INTO " + bufferTable + " "
+ "SELECT 1,ST_Multi(ST_UNION(ST_BUFFER(\"GEOMETRY\", "
+ bufferSize + "))) \"GEOMETRY\" FROM " + edgeTable;
final StringBuilder b = new StringBuilder("INSERT INTO ").append(bufferTable);
b.append(" SELECT 1,ST_Multi(ST_UNION(ST_BUFFER(\"GEOMETRY\", ").append(bufferSize).append("))) \"GEOMETRY\" FROM ").append(edgeTable);
PreparedStatement statement = null;
try {
statement = getPstmt(query);
statement = getPstmt(b.toString());
statement.executeUpdate();
connection.commit();
} catch (final SQLException e) {
......@@ -114,6 +108,36 @@ public class DatabaseWeb extends Database<ConfigClient> {
}
}
public List<Integer> edgesInArea(final int areaId) {
final List<Integer> edges = new ArrayList<Integer>();
final StringBuilder b = new StringBuilder("SELECT L.\"ID\" FROM ");
b.append(config.getEdgeTableEntry().getTableName()).append(" L, ");
b.append(config.getAreaBufferTableEntry().getTableName()).append(" A ");
b.append("WHERE A.\"ID\"=? AND ST_Within(L.\"GEOMETRY\",A.\"GEOMETRY\")=TRUE");
PreparedStatement statement = null;
ResultSet rs = null;
try {
statement = getPstmt(b.toString());
statement.setInt(1, areaId);
rs = statement.executeQuery();
while (rs.next()) {
edges.add(rs.getInt(1));
}
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(statement);
}
return edges;
}
public Connection getConnection() {
return connection;
}
@SuppressFBWarnings(
value = "DLS_DEAD_LOCAL_STORE",
justification = "False positiv in DLS_DEAD_LOCAL_STORE check"
......@@ -179,58 +203,64 @@ public class DatabaseWeb extends Database<ConfigClient> {
return isoEdges;
}
public void storeArea(final int areaId, final List<Point> points, final double bufferSize) {
final Geometry geometry = PgHelper.asPgGeometry(points);
final String geometryString = geometry.getTypeString() + geometry.getValue();
public Set<Location> projectOnLinks(final QueryNode qNode) {
Set<Location> locations = QueryNodeCache.getCachedQueryPoint(qNode);
if (locations != null) {
return locations;
}
final StringBuilder b = new StringBuilder();
b.append("INSERT INTO ").append(config.getAreaBufferTableEntry().getTableName());
b.append("(\"ID\",\"GEOMETRY\") VALUES(?,ST_MULTI(ST_Buffer(ST_MakeValid(ST_GeomFromText(?," + config.getServerSRID() + ")),?,'endcap=round join=round')))");
PreparedStatement statement = null;
final int clientSRID = ConfigIsochrone.getInstance().getClientSRID();
final String point = "POINT(" + qNode.getX() + " " + qNode.getY() + ")";
final StringBuilder sb = new StringBuilder();
sb.append("SELECT L.ID, ST_Line_Locate_Point(L.EDGE_GEO,L.POINT_GEO)*L.LENGTH AS OFFSET ");
sb.append("FROM (SELECT E.ID, E.GEOMETRY EDGE_GEO, E.LENGTH, P.GEOMETRY POINT_GEO FROM ");
sb.append(config.getTableEdges()).append(" E, ");
sb.append(" (SELECT ");
if (clientSRID == config.getServerSRID()) {
sb.append("ST_PointFromText(?,?) ");
} else {
sb.append("ST_Transform(ST_PointFromText(?,?),?)");
}
sb.append(" GEOMETRY) P");
sb.append(" WHERE E.EDGE_MODE=").append(NW_MODE_CONTINUOUS).append(" AND st_dwithin(E.GEOMETRY,P.GEOMETRY, ?)"); // tolerance
sb.append(" ORDER BY st_distance(E.GEOMETRY,P.GEOMETRY) LIMIT 2) L");
PreparedStatement statement = null;
ResultSet rSet = null;
try {
statement = getPstmt(b.toString());
statement = getPstmt(sb.toString());
statement.setString(1, point);
statement.setInt(2, clientSRID);
// CHECKSTYLE:OFF MagicNumber
statement.setInt(1, areaId);
statement.setString(2, geometryString);
statement.setDouble(3, bufferSize);
final int tolerance = config.getDistanceTolerance();
if (clientSRID != config.getServerSRID()) {
statement.setInt(3, config.getServerSRID());
statement.setInt(4, tolerance);
} else {
statement.setInt(3, tolerance);
}
// CHECKSTYLE:ON MagicNumber
statement.executeUpdate();
connection.commit();
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(statement);
}
}
public List<Integer> edgesInArea(final int areaId) {
final List<Integer> edges = new ArrayList<Integer>();
final StringBuilder b1 = new StringBuilder();
b1.append("SELECT L.\"ID\" FROM ");
b1.append(config.getEdgeTableEntry().getTableName()).append(" L, ");
b1.append(config.getAreaBufferTableEntry().getTableName()).append(" A ");
b1.append("WHERE A.\"ID\"=? AND ST_Within(L.\"GEOMETRY\",A.\"GEOMETRY\")=TRUE");
PreparedStatement statement = null;
ResultSet rs = null;
try {
statement = getPstmt(b1.toString());
statement.setInt(1, areaId);
rs = statement.executeQuery();
while (rs.next()) {
edges.add(rs.getInt(1));
rSet = statement.executeQuery();
locations = new HashSet<Location>();
while (rSet.next()) {
final int link = rSet.getInt("ID");
final double offset = rSet.getDouble("OFFSET");
locations.add(new Location(link, offset));
}
QueryNodeCache.addQueryNode(qNode, locations);
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(rSet);
DbUtils.closeQuietly(statement);
}
return edges;
return locations;
}
/*
/*
public int reachedInhabitants() {
int reachedInhabitants = 0;
final StringBuilder b = new StringBuilder();
......@@ -278,7 +308,32 @@ public class DatabaseWeb extends Database<ConfigClient> {
return totalInhabitants;
}
*/
*/
public void storeArea(final int areaId, final List<Point> points, final double bufferSize) {
final Geometry geometry = PgHelper.asPgGeometry(points);
final String geometryString = geometry.getTypeString() + geometry.getValue();
final StringBuilder b = new StringBuilder();
b.append("INSERT INTO ").append(config.getAreaBufferTableEntry().getTableName());
b.append("(\"ID\",\"GEOMETRY\") VALUES(?,ST_MULTI(ST_Buffer(ST_MakeValid(ST_GeomFromText(?," + config.getServerSRID() + ")),?,'endcap=round join=round')))");
PreparedStatement statement = null;
try {
statement = getPstmt(b.toString());
// CHECKSTYLE:OFF MagicNumber
statement.setInt(1, areaId);
statement.setString(2, geometryString);
statement.setDouble(3, bufferSize);
// CHECKSTYLE:ON MagicNumber
statement.executeUpdate();
connection.commit();
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(statement);
}
}
public final void storeLinks(final Collection<Link> links, final Direction direction) {
final boolean isIncoming = direction == Direction.INCOMING;
PreparedStatement statementPartial = null;
......@@ -330,63 +385,6 @@ public class DatabaseWeb extends Database<ConfigClient> {
}
}
public Set<Location> projectOnLinks(final QueryNode qNode) {
Set<Location> locations = QueryNodeCache.getCachedQueryPoint(qNode);
if (locations != null) {
return locations;
}
final int clientSRID = ConfigIsochrone.getInstance().getClientSRID();
final String point = "POINT(" + qNode.getX() + " " + qNode.getY() + ")";
final StringBuilder sb = new StringBuilder();
sb.append("SELECT L.ID, ST_Line_Locate_Point(L.EDGE_GEO,L.POINT_GEO)*L.LENGTH AS OFFSET ");
sb.append("FROM (SELECT E.ID, E.GEOMETRY EDGE_GEO, E.LENGTH, P.GEOMETRY POINT_GEO FROM ");
sb.append(config.getTableEdges()).append(" E, ");
sb.append(" (SELECT ");
if (clientSRID == config.getServerSRID()) {
sb.append("ST_PointFromText(?,?) ");
} else {
sb.append("ST_Transform(ST_PointFromText(?,?),?)");
}
sb.append(" GEOMETRY) P");
sb.append(" WHERE E.EDGE_MODE=").append(NW_MODE_CONTINUOUS).append(" AND st_dwithin(E.GEOMETRY,P.GEOMETRY, ?)"); // tolerance
sb.append(" ORDER BY st_distance(E.GEOMETRY,P.GEOMETRY) LIMIT 2) L");
PreparedStatement statement = null;
ResultSet rSet = null;
try {
statement = getPstmt(sb.toString());
statement.setString(1, point);
statement.setInt(2, clientSRID);
// CHECKSTYLE:OFF MagicNumber
final int tolerance = config.getDistanceTolerance();
if (clientSRID != config.getServerSRID()) {
statement.setInt(3, config.getServerSRID());
statement.setInt(4, tolerance);
} else {
statement.setInt(3, tolerance);
}
// CHECKSTYLE:ON MagicNumber
rSet = statement.executeQuery();
locations = new HashSet<Location>();
while (rSet.next()) {
final int link = rSet.getInt("ID");
final double offset = rSet.getDouble("OFFSET");
locations.add(new Location(link, offset));
}
QueryNodeCache.addQueryNode(qNode, locations);
} catch (final SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(rSet);
DbUtils.closeQuietly(statement);
}
return locations;
}
public void storeVertices(final Set<Node> nodes) {
PreparedStatement insertVerticesStatement = null;
PreparedStatement insertVertexAnnotationStatement = null;
......@@ -425,6 +423,11 @@ public class DatabaseWeb extends Database<ConfigClient> {
}
}
public Point transform(final Point p) {
final String query = "SELECT ST_X(P.GEO) X, ST_Y(P.GEO) Y FROM (SELECT ST_Transform(ST_PointFromText(?,?),?) GEO ) P";
return DatabaseWeb.transform(config, p, getPstmt(query));
}
public void updateVertexTable() {
PreparedStatement statement = null;
try {
......@@ -438,13 +441,14 @@ public class DatabaseWeb extends Database<ConfigClient> {
}
}
// Public static methods
public static Point transform(final ConfigDataset config, final Point p) {
return transform(config, p, null);
}
// Private static methods
private static Point transform(final ConfigDataset config, final Point p, final PreparedStatement preparedStatement) {
final ConfigIsochrone configIso = ConfigIsochrone.getInstance();
final boolean openNewStatement = (preparedStatement == null);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment