
org.opentripplanner.updater.vehicle_rental.VehicleRentalUpdater Maven / Gradle / Ivy
package org.opentripplanner.updater.vehicle_rental;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.opentripplanner.graph_builder.linking.DisposableEdgeCollection;
import org.opentripplanner.graph_builder.linking.LinkingDirection;
import org.opentripplanner.graph_builder.linking.VertexLinker;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.edgetype.StreetVehicleRentalLink;
import org.opentripplanner.routing.edgetype.VehicleRentalEdge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.vehicle_rental.RentalVehicleType.FormFactor;
import org.opentripplanner.routing.vehicle_rental.VehicleRentalPlace;
import org.opentripplanner.routing.vehicle_rental.VehicleRentalStationService;
import org.opentripplanner.routing.vertextype.VehicleRentalPlaceVertex;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.service.TransitModel;
import org.opentripplanner.updater.DataSource;
import org.opentripplanner.updater.GraphWriterRunnable;
import org.opentripplanner.updater.PollingGraphUpdater;
import org.opentripplanner.updater.UpdaterConstructionException;
import org.opentripplanner.updater.WriteToGraphCallback;
import org.opentripplanner.util.lang.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Dynamic vehicle-rental station updater which updates the Graph with vehicle rental stations from
* one VehicleRentalDataSource.
*/
public class VehicleRentalUpdater extends PollingGraphUpdater {
private static final Logger LOG = LoggerFactory.getLogger(VehicleRentalUpdater.class);
private final DataSource source;
private WriteToGraphCallback saveResultOnGraph;
Map verticesByStation = new HashMap<>();
Map tempEdgesByStation = new HashMap<>();
private VertexLinker linker;
private VehicleRentalStationService service;
public VehicleRentalUpdater(
VehicleRentalUpdaterParameters parameters,
DataSource source,
VertexLinker vertexLinker,
VehicleRentalStationService vehicleRentalStationService
) throws IllegalArgumentException {
super(parameters);
// Configure updater
LOG.info("Setting up vehicle rental updater.");
this.source = source;
// Creation of network linker library will not modify the graph
this.linker = vertexLinker;
// Adding a vehicle rental station service needs a graph writer runnable
this.service = vehicleRentalStationService;
try {
// Do any setup if needed
source.setup();
} catch (UpdaterConstructionException e) {
LOG.warn("Unable to setup updater: {}", parameters.getConfigRef(), e);
}
if (pollingPeriodSeconds() <= 0) {
LOG.info("Creating vehicle-rental updater running once only (non-polling): {}", source);
} else {
LOG.info(
"Creating vehicle-rental updater running every {} seconds: {}",
pollingPeriodSeconds(),
source
);
}
}
@Override
public void setGraphUpdaterManager(WriteToGraphCallback saveResultOnGraph) {
this.saveResultOnGraph = saveResultOnGraph;
}
@Override
public String toString() {
return ToStringBuilder.of(VehicleRentalUpdater.class).addObj("source", source).toString();
}
@Override
public String getConfigRef() {
return toString();
}
@Override
protected void runPolling() {
LOG.debug("Updating vehicle rental stations from {}", source);
if (!source.update()) {
LOG.debug("No updates");
return;
}
List stations = source.getUpdates();
// Create graph writer runnable to apply these stations to the graph
VehicleRentalGraphWriterRunnable graphWriterRunnable = new VehicleRentalGraphWriterRunnable(
stations
);
saveResultOnGraph.execute(graphWriterRunnable);
}
private class VehicleRentalGraphWriterRunnable implements GraphWriterRunnable {
private final List stations;
public VehicleRentalGraphWriterRunnable(List stations) {
this.stations = stations;
}
@Override
public void run(Graph graph, TransitModel transitModel) {
// Apply stations to graph
Set stationSet = new HashSet<>();
/* add any new stations and update vehicle counts for existing stations */
for (VehicleRentalPlace station : stations) {
service.addVehicleRentalStation(station);
stationSet.add(station.getId());
VehicleRentalPlaceVertex vehicleRentalVertex = verticesByStation.get(station.getId());
if (vehicleRentalVertex == null) {
vehicleRentalVertex = new VehicleRentalPlaceVertex(graph, station);
DisposableEdgeCollection tempEdges = linker.linkVertexForRealTime(
vehicleRentalVertex,
new TraverseModeSet(TraverseMode.WALK),
LinkingDirection.BOTH_WAYS,
(vertex, streetVertex) ->
List.of(
new StreetVehicleRentalLink((VehicleRentalPlaceVertex) vertex, streetVertex),
new StreetVehicleRentalLink(streetVertex, (VehicleRentalPlaceVertex) vertex)
)
);
if (vehicleRentalVertex.getOutgoing().isEmpty()) {
// the toString includes the text "Bike rental station"
LOG.info("VehicleRentalPlace {} is unlinked", vehicleRentalVertex);
}
Set formFactors = Stream
.concat(
station.getAvailablePickupFormFactors(false).stream(),
station.getAvailableDropoffFormFactors(false).stream()
)
.collect(Collectors.toSet());
for (FormFactor formFactor : formFactors) {
tempEdges.addEdge(new VehicleRentalEdge(vehicleRentalVertex, formFactor));
}
verticesByStation.put(station.getId(), vehicleRentalVertex);
tempEdgesByStation.put(station.getId(), tempEdges);
} else {
vehicleRentalVertex.setStation(station);
}
}
/* remove existing stations that were not present in the update */
List toRemove = new ArrayList<>();
for (Entry entry : verticesByStation.entrySet()) {
FeedScopedId station = entry.getKey();
if (stationSet.contains(station)) continue;
toRemove.add(station);
service.removeVehicleRentalStation(station);
}
for (FeedScopedId station : toRemove) {
// post-iteration removal to avoid concurrent modification
verticesByStation.remove(station);
tempEdgesByStation.get(station).disposeEdges();
tempEdgesByStation.remove(station);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy