com.conveyal.gtfs.loader.EntityPopulator Maven / Gradle / Ivy
package com.conveyal.gtfs.loader;
import com.conveyal.gtfs.model.*;
import gnu.trove.map.TObjectIntMap;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDate;
import java.sql.ResultSet;
import java.sql.SQLException;
import static com.conveyal.gtfs.model.Entity.INT_MISSING;
/**
* For now we will copy all available fields into Java model objects.
*
* We could also have entity cursors with accessor functions that move along the results, and only look at
* the fields we need. We could even select only the required fields from the backend database but that gets
* messy. Anecdotal evidence suggests this would give about a 1/3 speedup. But other observations show no speedup at all.
* The main benefit would be grabbing arbitrary extension columns.
*
* TODO associate EntityPopulator more closely with Entity types and Table instances, so you can get one from the other.
* e.g. getEntityPopulator() and getTableSpec() on Entity classes.
*
* TODO maybe instantiate EntityCreators with a columnForName map to avoid passing them around and make them implement Iterable
* Could even initialize with the resultSet and call it a Factory
*
* // FIXME URLs?
*
* This might also be useable with Commons DBUtils as a result row processor.
*
* // FIXME add this interface to Entity itself. And add reader / writer functions to entity as well?
*/
public interface EntityPopulator {
public T populate (ResultSet results, TObjectIntMap columnForName) throws SQLException;
public static final EntityPopulator AGENCY = (result, columnForName) -> {
Agency agency = new Agency();
agency.agency_id = getStringIfPresent(result, "agency_id", columnForName);
agency.agency_name = getStringIfPresent(result, "agency_name", columnForName);
agency.agency_url = getUrlIfPresent (result, "agency_url", columnForName);
agency.agency_timezone = getStringIfPresent(result, "agency_timezone", columnForName);
agency.agency_lang = getStringIfPresent(result, "agency_lang", columnForName);
agency.agency_phone = getStringIfPresent(result, "agency_phone", columnForName);
agency.agency_fare_url = getUrlIfPresent (result, "agency_fare_url", columnForName);
agency.agency_email = getStringIfPresent(result, "agency_email", columnForName);
agency.agency_branding_url = null; // FIXME
return agency;
};
public static final EntityPopulator CALENDAR = (result, columnForName) -> {
Calendar calendar = new Calendar();
calendar.service_id = getStringIfPresent(result, "service_id", columnForName);
calendar.start_date = getDateIfPresent (result, "start_date", columnForName);
calendar.end_date = getDateIfPresent (result, "end_date", columnForName);
calendar.monday = getIntIfPresent (result, "monday", columnForName);
calendar.tuesday = getIntIfPresent (result, "tuesday", columnForName);
calendar.wednesday = getIntIfPresent (result, "wednesday", columnForName);
calendar.thursday = getIntIfPresent (result, "thursday", columnForName);
calendar.friday = getIntIfPresent (result, "friday", columnForName);
calendar.saturday = getIntIfPresent (result, "saturday", columnForName);
calendar.sunday = getIntIfPresent (result, "sunday", columnForName);
return calendar;
};
public static final EntityPopulator CALENDAR_DATE = (result, columnForName) -> {
CalendarDate calendarDate = new CalendarDate();
calendarDate.service_id = getStringIfPresent(result, "service_id", columnForName);
calendarDate.date = getDateIfPresent (result, "date", columnForName);
calendarDate.exception_type = getIntIfPresent (result, "exception_type", columnForName);
return calendarDate;
};
public static final EntityPopulator ROUTE = (result, columnForName) -> {
Route route = new Route();
route.route_id = getStringIfPresent(result, "route_id", columnForName);
route.agency_id = getStringIfPresent(result, "agency_id", columnForName);
route.route_short_name = getStringIfPresent(result, "route_short_name", columnForName);
route.route_long_name = getStringIfPresent(result, "route_long_name", columnForName);
route.route_desc = getStringIfPresent(result, "route_desc", columnForName);
route.route_type = getIntIfPresent (result, "route_type", columnForName);
route.route_color = getStringIfPresent(result, "route_color", columnForName);
route.route_text_color = getStringIfPresent(result, "route_text_color", columnForName);
route.route_url = getUrlIfPresent (result, "route_url", columnForName);;
route.route_branding_url = getUrlIfPresent (result, "route_branding_url", columnForName);;
return route;
};
public static final EntityPopulator STOP = (result, columnForName) -> {
Stop stop = new Stop();
stop.stop_id = getStringIfPresent(result, "stop_id", columnForName);
stop.stop_code = getStringIfPresent(result, "stop_code", columnForName);
stop.stop_name = getStringIfPresent(result, "stop_name", columnForName);
stop.stop_desc = getStringIfPresent(result, "stop_desc", columnForName);
stop.stop_lat = getDoubleIfPresent(result, "stop_lat", columnForName);
stop.stop_lon = getDoubleIfPresent(result, "stop_lon", columnForName);
stop.zone_id = getStringIfPresent(result, "zone_id", columnForName);
stop.parent_station = getStringIfPresent(result, "parent_station", columnForName);
stop.stop_timezone = getStringIfPresent(result, "stop_timezone", columnForName);
stop.stop_url = getUrlIfPresent (result, "stop_url", columnForName);
stop.location_type = getIntIfPresent (result, "location_type", columnForName);
stop.wheelchair_boarding = Integer.toString(getIntIfPresent(result, "wheelchair_boarding", columnForName));
return stop;
};
public static final EntityPopulator TRIP = (result, columnForName) -> {
Trip trip = new Trip();
trip.trip_id = getStringIfPresent(result, "trip_id", columnForName);
trip.route_id = getStringIfPresent(result, "route_id", columnForName);
trip.service_id = getStringIfPresent(result, "service_id", columnForName);
trip.trip_headsign = getStringIfPresent(result, "trip_headsign", columnForName);
trip.trip_short_name = getStringIfPresent(result, "trip_short_name", columnForName);
trip.block_id = getStringIfPresent(result, "block_id", columnForName);
trip.shape_id = getStringIfPresent(result, "shape_id", columnForName);
trip.direction_id = getIntIfPresent (result, "direction_id", columnForName);
trip.bikes_allowed = getIntIfPresent (result, "bikes_allowed", columnForName);
trip.wheelchair_accessible = getIntIfPresent(result, "wheelchair_accessible", columnForName);
return trip;
};
public static final EntityPopulator SHAPE_POINT = (result, columnForName) -> {
ShapePoint shapePoint = new ShapePoint();
shapePoint.shape_id = getStringIfPresent(result, "shape_id", columnForName);
shapePoint.shape_pt_lat = getDoubleIfPresent(result, "shape_pt_lat", columnForName);
shapePoint.shape_pt_lon = getDoubleIfPresent(result, "shape_pt_lon", columnForName);
shapePoint.shape_pt_sequence = getIntIfPresent(result, "shape_pt_sequence", columnForName);
shapePoint.shape_dist_traveled = getDoubleIfPresent(result, "shape_dist_traveled", columnForName);
return shapePoint;
};
public static final EntityPopulator STOP_TIME = (result, columnForName) -> {
StopTime stopTime = new StopTime();
stopTime.trip_id = getStringIfPresent(result, "trip_id", columnForName);
stopTime.arrival_time = getIntIfPresent (result, "arrival_time", columnForName);
stopTime.departure_time = getIntIfPresent (result, "departure_time", columnForName);
stopTime.stop_id = getStringIfPresent(result, "stop_id", columnForName);
stopTime.stop_sequence = getIntIfPresent (result, "stop_sequence", columnForName);
stopTime.stop_headsign = getStringIfPresent(result, "stop_headsign", columnForName);
stopTime.pickup_type = getIntIfPresent (result, "pickup_type", columnForName);
stopTime.drop_off_type = getIntIfPresent (result, "drop_off_type", columnForName);
stopTime.timepoint = getIntIfPresent (result, "timepoint", columnForName);
stopTime.shape_dist_traveled = getDoubleIfPresent(result, "shape_dist_traveled", columnForName);
return stopTime;
};
// The reason we're passing in the columnForName map is that resultSet.getX(columnName) throws an exception
// when the column is not present.
// Exceptions should only be used in exceptional circumstances (ones that should be logged as errors).
// Conceivably we could iterate over the fields present using ResultSetMetaData and set the object fields only
// for those fields present. Or we could create cursor objects that allow accessing the fields of the ResultSet
// in a typed way. Those cursor objects would make their own columnForName map when constructed.
public static String getStringIfPresent (ResultSet resultSet, String columnName,
TObjectIntMap columnForName) throws SQLException {
int columnIndex = columnForName.get(columnName);
if (columnIndex == 0) return null;
else return resultSet.getString(columnIndex);
}
public static LocalDate getDateIfPresent (ResultSet resultSet, String columnName,
TObjectIntMap columnForName) throws SQLException {
int columnIndex = columnForName.get(columnName);
if (columnIndex == 0) return null;
else return LocalDate.parse(resultSet.getString(columnIndex), DateField.GTFS_DATE_FORMATTER);
}
public static URL getUrlIfPresent (ResultSet resultSet, String columnName,
TObjectIntMap columnForName) throws SQLException {
int columnIndex = columnForName.get(columnName);
if (columnIndex == 0) return null;
try {
URL url = new URL(resultSet.getString(columnIndex));
return url;
} catch (MalformedURLException e) {
return null;
}
}
// FIXME: Do we need a method to get LocalDate for calendar tables?
// public static LocalDate getDateIfPresent (ResultSet resultSet, String columnName,
// TObjectIntMap columnForName) throws SQLException {
// int columnIndex = columnForName.get(columnName);
// if (columnIndex == 0) return -1;
// else return resultSet.get(columnIndex);
// }
public static double getDoubleIfPresent (ResultSet resultSet, String columnName,
TObjectIntMap columnForName) throws SQLException {
int columnIndex = columnForName.get(columnName);
if (columnIndex == 0) return -1;
else return resultSet.getDouble(columnIndex);
}
public static int getIntIfPresent (ResultSet resultSet, String columnName,
TObjectIntMap columnForName) throws SQLException {
int columnIndex = columnForName.get(columnName);
if (columnIndex == 0) return -1;
else return resultSet.getInt(columnIndex);
}
// This really crushes incorrect values... maybe we should just be using int.
public static boolean getBooleanIfPresent (ResultSet resultSet, String columnName,
TObjectIntMap columnForName) throws SQLException {
int columnIndex = columnForName.get(columnName);
if (columnIndex == 0) return false;
else return resultSet.getBoolean(columnIndex);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy