public void record(FeedMessage feedMessage) throws SQLException { int numAlerts = 0; int numTripUpdates = 0; int numVehiclePositions = 0; mOpenQueries = 0; for (FeedEntity entity : feedMessage.getEntityList()) { if (entity.hasAlert()) { numAlerts++; } if (entity.hasTripUpdate()) { numTripUpdates++; } if (entity.hasVehicle()) { numVehiclePositions++; } } boolean hasAlerts = numAlerts > 0; boolean hasTripUpdates = numTripUpdates > 0; boolean hasVehiclePositions = numVehiclePositions > 0; mLogger.info( String.format( "Entities: alerts=%d, updates=%d, positions=%d", numAlerts, numTripUpdates, numVehiclePositions)); mLogger.info("Clearing tables..."); if (hasAlerts) { clearAlertsData(); } if (hasTripUpdates) { clearTripUpdatesData(); } if (hasVehiclePositions) { clearVehiclePositionsData(); } mLogger.info("Finished clearing tables"); if (!hasAlerts && !hasTripUpdates && !hasVehiclePositions) { mLogger.info("Nothing to record"); return; } boolean useCopy = mConnection instanceof BaseConnection; CopyManager cm = null; DataCopier tuCopier = null; DataCopier stCopier = null; DataCopier vpCopier = null; CopyIn tuCopyIn = null; CopyIn stCopyIn = null; CopyIn vpCopyIn = null; if (useCopy) { cm = new CopyManager((BaseConnection) mConnection); tuCopier = new DataCopier(); stCopier = new DataCopier(); vpCopier = new DataCopier(); if (hasTripUpdates) { stCopyIn = cm.copyIn(COPY_TRIP_UPDATES_STOP_TIMES); mOpenQueries++; stCopier = new DataCopier(stCopyIn, COPY_SEPARATOR); } else if (hasVehiclePositions) { vpCopyIn = cm.copyIn(COPY_VEHICLE_POSITIONS); mOpenQueries++; vpCopier = new DataCopier(vpCopyIn, COPY_SEPARATOR); } } for (FeedEntity entity : feedMessage.getEntityList()) { if (entity.hasAlert()) { try { recordAlert(entity.getAlert()); } catch (SQLException e) { mLogger.warning(getString(e)); } } if (entity.hasTripUpdate()) { try { recordTripUpdate(entity.getTripUpdate(), tuCopier, stCopier); } catch (Exception e) { mLogger.warning(getString(e)); } } if (entity.hasVehicle()) { try { recordVehicle(entity.getVehicle(), vpCopier); } catch (Exception e) { mLogger.warning(getString(e)); } } } if (hasAlerts) { mLogger.info("Committing alerts... "); try { mStatements.get(STALERT).executeBatch(); mStatements.get(STALERT_ENTITIES).executeBatch(); mStatements.get(STALERT_TIMERANGES).executeBatch(); mLogger.info("done"); } catch (Exception e) { mLogger.warning(getString(e)); } } if (hasTripUpdates) { mLogger.info("Committing trip updates... "); try { if (stCopier == null) { mStatements.get(STTRIPUPDATE_STOPTIMEUPDATES).executeBatch(); } else if (stCopyIn == null && stCopier.size() > 0) { stCopyIn = cm.copyIn(COPY_TRIP_UPDATES_STOP_TIMES); mOpenQueries++; stCopier.write(stCopyIn, COPY_SEPARATOR); } } catch (SQLException e) { e.printStackTrace(); } if (stCopyIn != null) { try { stCopyIn.endCopy(); mOpenQueries--; } catch (Exception e) { mLogger.warning(getString(e)); } } try { if (tuCopier == null) { mStatements.get(STTRIPUPDATE).executeBatch(); } else if (tuCopyIn == null && tuCopier.size() > 0) { tuCopyIn = cm.copyIn(COPY_TRIP_UPDATES); mOpenQueries++; tuCopier.write(tuCopyIn, COPY_SEPARATOR); } } catch (SQLException e) { e.printStackTrace(); } if (tuCopyIn != null) { try { tuCopyIn.endCopy(); mOpenQueries--; } catch (Exception e) { mLogger.warning(getString(e)); } } mLogger.info("done"); } if (hasVehiclePositions) { System.err.print("Committing vehicle positions... "); try { if (vpCopier == null) { mStatements.get(STVEHICLE).executeBatch(); } else if (vpCopyIn == null && vpCopier.size() > 0) { vpCopyIn = cm.copyIn(COPY_VEHICLE_POSITIONS); mOpenQueries++; vpCopier.write(vpCopyIn, COPY_SEPARATOR); } } catch (Exception e) { mLogger.warning(getString(e)); } if (vpCopyIn != null) { vpCopyIn.endCopy(); mOpenQueries--; } mLogger.info("done"); } }
/** * This method downloads the latest vehicle data, processes each vehicle in turn, and create a * GTFS-realtime feed of trip updates and vehicle positions as a result. */ private void refreshVehicles() throws IOException, JSONException { /** We download the vehicle details as an array of JSON objects. */ JSONArray vehicleArray = downloadVehicleDetails(); /** * The FeedMessage.Builder is what we will use to build up our GTFS-realtime feeds. We create a * feed for both trip updates and vehicle positions. */ FeedMessage.Builder tripUpdates = GtfsRealtimeLibrary.createFeedMessageBuilder(); FeedMessage.Builder vehiclePositions = GtfsRealtimeLibrary.createFeedMessageBuilder(); /** We iterate over every JSON vehicle object. */ for (int i = 0; i < vehicleArray.length(); ++i) { JSONObject obj = vehicleArray.getJSONObject(i); String trainNumber = obj.getString("trainno"); String route = obj.getString("dest"); String stopId = obj.getString("nextstop"); double lat = obj.getDouble("lat"); double lon = obj.getDouble("lon"); int delay = obj.getInt("late"); /** * We construct a TripDescriptor and VehicleDescriptor, which will be used in both trip * updates and vehicle positions to identify the trip and vehicle. Ideally, we would have a * trip id to use for the trip descriptor, but the SEPTA api doesn't include it, so we settle * for a route id instead. */ TripDescriptor.Builder tripDescriptor = TripDescriptor.newBuilder(); tripDescriptor.setRouteId(route); VehicleDescriptor.Builder vehicleDescriptor = VehicleDescriptor.newBuilder(); vehicleDescriptor.setId(trainNumber); /** * To construct our TripUpdate, we create a stop-time arrival event for the next stop for the * vehicle, with the specified arrival delay. We add the stop-time update to a TripUpdate * builder, along with the trip and vehicle descriptors. */ StopTimeEvent.Builder arrival = StopTimeEvent.newBuilder(); arrival.setDelay(delay * 60); StopTimeUpdate.Builder stopTimeUpdate = StopTimeUpdate.newBuilder(); stopTimeUpdate.setArrival(arrival); stopTimeUpdate.setStopId(stopId); TripUpdate.Builder tripUpdate = TripUpdate.newBuilder(); tripUpdate.addStopTimeUpdate(stopTimeUpdate); tripUpdate.setTrip(tripDescriptor); tripUpdate.setVehicle(vehicleDescriptor); /** * Create a new feed entity to wrap the trip update and add it to the GTFS-realtime trip * updates feed. */ FeedEntity.Builder tripUpdateEntity = FeedEntity.newBuilder(); tripUpdateEntity.setId(trainNumber); tripUpdateEntity.setTripUpdate(tripUpdate); tripUpdates.addEntity(tripUpdateEntity); /** * To construct our VehiclePosition, we create a position for the vehicle. We add the position * to a VehiclePosition builder, along with the trip and vehicle descriptors. */ Position.Builder position = Position.newBuilder(); position.setLatitude((float) lat); position.setLongitude((float) lon); VehiclePosition.Builder vehiclePosition = VehiclePosition.newBuilder(); vehiclePosition.setPosition(position); vehiclePosition.setTrip(tripDescriptor); vehiclePosition.setVehicle(vehicleDescriptor); /** * Create a new feed entity to wrap the vehicle position and add it to the GTFS-realtime * vehicle positions feed. */ FeedEntity.Builder vehiclePositionEntity = FeedEntity.newBuilder(); vehiclePositionEntity.setId(trainNumber); vehiclePositionEntity.setVehicle(vehiclePosition); vehiclePositions.addEntity(vehiclePositionEntity); } /** Build out the final GTFS-realtime feed messagse and save them. */ _gtfsRealtimeProvider.setTripUpdates(tripUpdates.build()); _gtfsRealtimeProvider.setVehiclePositions(vehiclePositions.build()); _log.info("vehicles extracted: " + tripUpdates.getEntityCount()); }