/* The MIT License (MIT) * * Copyright (c) 2015 Reinventing Geospatial, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.rgi.geopackage.extensions.network; import com.rgi.common.util.jdbc.JdbcUtility; import com.rgi.common.util.jdbc.SavedParameterizedQuery; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; import java.util.List; /** * @author Luke Lambert */ public class NodeExitGetter extends SavedParameterizedQuery<List<AttributedEdge>> { /** * Constructor * * @param nodeAttributeDescriptions * Collection of attributes that will be retrieved for the * edge's two endpoints * @param edgeAttributeDescriptions * Collection of attributes that will be retrieved for the * edge * @throws SQLException * if there is a database error */ protected NodeExitGetter(final Connection databaseConnection, final Network network, final Collection<AttributeDescription> nodeAttributeDescriptions, final Collection<AttributeDescription> edgeAttributeDescriptions) throws SQLException { super(databaseConnection, () -> { final StringBuilder edgeAttributes = new StringBuilder(); if(edgeAttributeDescriptions != null) { for(final AttributeDescription attribute : edgeAttributeDescriptions) { edgeAttributes.append(String.format(", edge.%s", attribute.getName())); } } final StringBuilder nodeAttributes = new StringBuilder(); if(nodeAttributeDescriptions != null) { for(final AttributeDescription attribute : nodeAttributeDescriptions) { nodeAttributes.append(String.format(", f.%s", attribute.getName())); // from_node attributes, 'f' } for(final AttributeDescription attribute : nodeAttributeDescriptions) { nodeAttributes.append(String.format(", t.%s", attribute.getName())); // to_node attributes, 't' } } return String.format("SELECT edge.id, edge.to_node%1$s%2$s\n" + "FROM %3$s as f,\n" + " %3$s as t,\n" + " (SELECT id, to_node%1$s\n" + " FROM %4$s\n" + " WHERE from_node = ?) as edge\n" + "WHERE f.node_id = ? AND t.node_id = to_node;", edgeAttributes.toString(), // %1$s additional requested edge attributes to query for nodeAttributes.toString(), // %2$s requested node attributes to query for GeoPackageNetworkExtension.getNodeAttributesTableName(network), // %3$s node attribute table name network.getTableName()); // %4$s network table name; }); final int edgeAttributeCount = edgeAttributeDescriptions == null ? 0 : edgeAttributeDescriptions.size(); final int nodeAttributeCount = nodeAttributeDescriptions == null ? 0 : nodeAttributeDescriptions.size(); this.firstEdgeAttributeColumn = 3; // Edge attributes always start after edge.id and edge.to_node, and column indices are 1-based this.lastEdgeAttributeColumn = this.firstEdgeAttributeColumn + edgeAttributeCount; this.firstFromNodeAttributeColumn = edgeAttributeCount == 0 ? this.firstEdgeAttributeColumn : this.lastEdgeAttributeColumn + 1; // From node attributes follow edge attributes this.lastFromNodeAttributeColumn = this.firstFromNodeAttributeColumn + nodeAttributeCount - 1; this.firstToNodeAttributeColumn = nodeAttributeCount == 0 ? this.firstFromNodeAttributeColumn : this.lastFromNodeAttributeColumn + 1; // To node attributes follow edge attributes this.lastToNodeAttributeColumn = this.firstToNodeAttributeColumn + nodeAttributeCount - 1; } /** * Returns a collection of edge that represent exits from the supplied node * * @param fromNodeIdentifier * 'From' node identifier * @return a collection of edge that represent exits from the supplied node * @throws SQLException * if there is a database error */ public List<AttributedEdge> getExits(final int fromNodeIdentifier) throws SQLException { this.fromNodeIdentifier = fromNodeIdentifier; this.getPreparedStatement().setInt(1, fromNodeIdentifier); this.getPreparedStatement().setInt(2, fromNodeIdentifier); return this.execute(); } @Override protected List<AttributedEdge> processResult(final ResultSet resultSet) throws SQLException { return JdbcUtility.map(resultSet, results -> new AttributedEdge(results.getInt(1), // edge identifier NodeExitGetter.this.getEdgeAttributes(results), new AttributedNode(this.fromNodeIdentifier, NodeExitGetter.this.getFromNodeAttributes(results)), new AttributedNode(resultSet.getInt(2), NodeExitGetter.this.getToNodeAttributes(results)))); } protected List<Object> getEdgeAttributes(final ResultSet resultSet) throws SQLException { return this.firstEdgeAttributeColumn < this.lastEdgeAttributeColumn ? JdbcUtility.getObjects(resultSet, this.firstEdgeAttributeColumn, this.lastEdgeAttributeColumn) : null; } protected List<Object> getFromNodeAttributes(final ResultSet resultSet) throws SQLException { return this.firstFromNodeAttributeColumn < this.lastFromNodeAttributeColumn ? JdbcUtility.getObjects(resultSet, this.firstFromNodeAttributeColumn, this.lastFromNodeAttributeColumn) : null; } protected List<Object> getToNodeAttributes(final ResultSet resultSet) throws SQLException { return this.firstToNodeAttributeColumn < this.lastToNodeAttributeColumn ? JdbcUtility.getObjects(resultSet, this.firstToNodeAttributeColumn, this.lastToNodeAttributeColumn) : null; } private final int firstEdgeAttributeColumn; private final int lastEdgeAttributeColumn; private final int firstFromNodeAttributeColumn; private final int lastFromNodeAttributeColumn; private final int firstToNodeAttributeColumn; private final int lastToNodeAttributeColumn; private int fromNodeIdentifier; }