All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.opentripplanner.updater.vehicle_parking.VehicleParkingUpdater Maven / Gradle / Ivy
package org.opentripplanner.updater.vehicle_parking;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.opentripplanner.graph_builder.linking.DisposableEdgeCollection;
import org.opentripplanner.graph_builder.linking.LinkingDirection;
import org.opentripplanner.graph_builder.linking.VertexLinker;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.edgetype.StreetVehicleParkingLink;
import org.opentripplanner.routing.edgetype.VehicleParkingEdge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.vehicle_parking.VehicleParking;
import org.opentripplanner.routing.vehicle_parking.VehicleParkingHelper;
import org.opentripplanner.routing.vehicle_parking.VehicleParkingService;
import org.opentripplanner.routing.vehicle_parking.VehicleParkingState;
import org.opentripplanner.routing.vertextype.VehicleParkingEntranceVertex;
import org.opentripplanner.updater.DataSource;
import org.opentripplanner.updater.GraphWriterRunnable;
import org.opentripplanner.updater.PollingGraphUpdater;
import org.opentripplanner.updater.WriteToGraphCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Graph updater that dynamically sets availability information on vehicle parking lots.
* This updater fetches data from a single {@link DataSource}.
*/
public class VehicleParkingUpdater extends PollingGraphUpdater {
private static final Logger LOG = LoggerFactory.getLogger(VehicleParkingUpdater.class);
private WriteToGraphCallback saveResultOnGraph;
private final Map> verticesByPark = new HashMap<>();
private final Map> tempEdgesByPark = new HashMap<>();
private final DataSource source;
private final List oldVehicleParkings = new ArrayList<>();
private VertexLinker linker;
private VehicleParkingService vehicleParkingService;
public VehicleParkingUpdater(VehicleParkingUpdaterParameters parameters, DataSource source) {
super(parameters);
this.source = source;
LOG.info("Creating vehicle-parking updater running every {} seconds : {}", pollingPeriodSeconds, source);
}
@Override
public void setGraphUpdaterManager(WriteToGraphCallback saveResultOnGraph) {
this.saveResultOnGraph = saveResultOnGraph;
}
@Override
public void setup(Graph graph) {
// Creation of network linker library will not modify the graph
linker = graph.getLinker();
// Adding a vehicle parking station service needs a graph writer runnable
vehicleParkingService = graph.getService(VehicleParkingService.class, true);
}
@Override
protected void runPolling() throws Exception {
LOG.debug("Updating vehicle parkings from " + source);
if (!source.update()) {
LOG.debug("No updates");
return;
}
List vehicleParkings = source.getUpdates();
// Create graph writer runnable to apply these stations to the graph
VehicleParkingGraphWriterRunnable graphWriterRunnable = new VehicleParkingGraphWriterRunnable(vehicleParkings);
saveResultOnGraph.execute(graphWriterRunnable);
}
@Override
public void teardown() {
}
private class VehicleParkingGraphWriterRunnable implements GraphWriterRunnable {
private final Map oldVehicleParkingsById;
private final Set updatedVehicleParkings;
private VehicleParkingGraphWriterRunnable(List updatedVehicleParkings) {
this.oldVehicleParkingsById = oldVehicleParkings.stream()
.collect(Collectors.toMap(VehicleParking::getId, Function.identity()));
this.updatedVehicleParkings = new HashSet<>(updatedVehicleParkings);
}
@Override
public void run(Graph graph) {
// Apply stations to graph
/* Add any new park and update space available for existing parks */
Set toAdd = new HashSet<>();
Set toLink = new HashSet<>();
Set toRemove = new HashSet<>();
for (VehicleParking updatedVehicleParking : updatedVehicleParkings) {
var operational = updatedVehicleParking.getState().equals(VehicleParkingState.OPERATIONAL);
var alreadyExists = oldVehicleParkings.contains(updatedVehicleParking);
if (alreadyExists) {
oldVehicleParkingsById.get(updatedVehicleParking.getId())
.updateAvailability(updatedVehicleParking.getAvailability());
} else {
toAdd.add(updatedVehicleParking);
if (operational) {
toLink.add(updatedVehicleParking);
}
}
}
/* Remove existing parks that were not present in the update */
for (var oldVehicleParking : oldVehicleParkings) {
if (updatedVehicleParkings.contains(oldVehicleParking)) {
continue;
}
vehicleParkingService.removeVehicleParking(oldVehicleParking);
if (verticesByPark.containsKey(oldVehicleParking)) {
tempEdgesByPark.get(oldVehicleParking)
.forEach(DisposableEdgeCollection::disposeEdges);
verticesByPark.get(oldVehicleParking)
.forEach(v -> removeVehicleParkingEdgesFromGraph(v, graph));
verticesByPark.remove(oldVehicleParking);
}
toRemove.add(oldVehicleParking);
}
/* Add new parks, after removing, so that there are no duplicate vertices for removed and re-added parks.*/
for (final VehicleParking updatedVehicleParking : toLink) {
var vehicleParkingVertices = VehicleParkingHelper.createVehicleParkingVertices(graph, updatedVehicleParking);
var disposableEdgeCollectionsForVertex = linkVehicleParkingVertexToStreets(vehicleParkingVertices);
VehicleParkingHelper.linkVehicleParkingEntrances(vehicleParkingVertices);
verticesByPark.put(updatedVehicleParking, vehicleParkingVertices);
tempEdgesByPark.put(updatedVehicleParking, disposableEdgeCollectionsForVertex);
}
for (final VehicleParking vehicleParking : toAdd) {
vehicleParkingService.addVehicleParking(vehicleParking);
}
oldVehicleParkings.removeAll(toRemove);
oldVehicleParkings.addAll(toAdd);
}
private List linkVehicleParkingVertexToStreets(List vehicleParkingVertices) {
List disposableEdgeCollectionsForVertex = new ArrayList<>();
for (var vehicleParkingVertex : vehicleParkingVertices) {
var disposableEdges = linkVehicleParkingForRealtime(vehicleParkingVertex);
disposableEdgeCollectionsForVertex.addAll(disposableEdges);
if (vehicleParkingVertex.getOutgoing().isEmpty()) {
LOG.info("Vehicle parking {} unlinked", vehicleParkingVertex);
}
}
return disposableEdgeCollectionsForVertex;
}
private List linkVehicleParkingForRealtime(
VehicleParkingEntranceVertex vehicleParkingEntranceVertex) {
List disposableEdgeCollections = new ArrayList<>();
if (vehicleParkingEntranceVertex.isWalkAccessible()) {
var disposableWalkEdges = linker.linkVertexForRealTime(
vehicleParkingEntranceVertex,
new TraverseModeSet(TraverseMode.WALK),
LinkingDirection.BOTH_WAYS,
(vertex, streetVertex) -> List.of(
new StreetVehicleParkingLink((VehicleParkingEntranceVertex) vertex, streetVertex),
new StreetVehicleParkingLink(streetVertex, (VehicleParkingEntranceVertex) vertex)
));
disposableEdgeCollections.add(disposableWalkEdges);
}
if (vehicleParkingEntranceVertex.isCarAccessible()) {
var disposableCarEdges = linker.linkVertexForRealTime(
vehicleParkingEntranceVertex,
new TraverseModeSet(TraverseMode.CAR),
LinkingDirection.BOTH_WAYS,
(vertex, streetVertex) -> List.of(
new StreetVehicleParkingLink((VehicleParkingEntranceVertex) vertex, streetVertex),
new StreetVehicleParkingLink(streetVertex, (VehicleParkingEntranceVertex) vertex)
));
disposableEdgeCollections.add(disposableCarEdges);
}
return disposableEdgeCollections;
}
private void removeVehicleParkingEdgesFromGraph(VehicleParkingEntranceVertex entranceVertex, Graph graph) {
entranceVertex.getIncoming().stream().filter(VehicleParkingEdge.class::isInstance).forEach(graph::removeEdge);
entranceVertex.getOutgoing().stream().filter(VehicleParkingEdge.class::isInstance).forEach(graph::removeEdge);
graph.remove(entranceVertex);
}
}
}