diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index c0deb932418..49cf3601502 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -1,12 +1,14 @@ package org.opentripplanner.graph_builder.module; import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ConcurrentHashMap; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; import org.opentripplanner.graph_builder.issues.StopNotLinkedForTransfers; @@ -17,6 +19,7 @@ import org.opentripplanner.graph_builder.module.nearbystops.StreetNearbyStopFinder; import org.opentripplanner.model.PathTransfer; import org.opentripplanner.routing.api.request.RouteRequest; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graphfinder.NearbyStop; import org.opentripplanner.street.model.edge.Edge; @@ -81,27 +84,35 @@ public void buildGraph() { AtomicInteger nTransfersTotal = new AtomicInteger(); AtomicInteger nLinkedStops = new AtomicInteger(); - // This is a synchronizedMultimap so that a parallel stream may be used to insert elements. - var transfersByStop = Multimaps.synchronizedMultimap( - HashMultimap.create() - ); + Map> transfersByStopForMode = + new ConcurrentHashMap<>(); + for (RouteRequest transferProfile : transferRequests) { + StreetMode mode = transferProfile.journey().transfer().mode(); + // This is a synchronizedMultimap so that a parallel stream may be used to insert elements. + transfersByStopForMode.put(mode, Multimaps.synchronizedMultimap( + HashMultimap.create() + )); + } stops .stream() .parallel() .forEach(ts0 -> { - /* Make transfers to each nearby stop that has lowest weight on some trip pattern. - * Use map based on the list of edges, so that only distinct transfers are stored. */ - Map distinctTransfers = new HashMap<>(); RegularStop stop = ts0.getStop(); if (stop.transfersNotAllowed()) { return; } - LOG.debug("Linking stop '{}' {}", stop, ts0); - for (RouteRequest transferProfile : transferRequests) { + StreetMode mode = transferProfile.journey().transfer().mode(); + + /* Make transfers to each nearby stop that has lowest weight on some trip pattern. + * Use map based on the list of edges, so that only distinct transfers are stored. */ + Map distinctTransfers = new HashMap<>(); + + LOG.debug("Linking stop '{}' {} for mode {}.", stop, ts0, mode); + for (NearbyStop sd : nearbyStopFinder.findNearbyStops( ts0, transferProfile, @@ -142,29 +153,30 @@ public void buildGraph() { ); } } - } - LOG.debug( - "Linked stop {} with {} transfers to stops with different patterns.", - stop, - distinctTransfers.size() - ); - if (distinctTransfers.isEmpty()) { - issueStore.add(new StopNotLinkedForTransfers(ts0)); - } else { - distinctTransfers - .values() - .forEach(transfer -> transfersByStop.put(transfer.from, transfer)); - nLinkedStops.incrementAndGet(); - nTransfersTotal.addAndGet(distinctTransfers.size()); - } + LOG.debug( + "Linked stop {} with {} transfers to stops with different patterns for mode {}.", + stop, + distinctTransfers.size(), + mode + ); + if (distinctTransfers.isEmpty()) { + issueStore.add(new StopNotLinkedForTransfers(ts0)); + } else { + distinctTransfers + .values() + .forEach(transfer -> transfersByStopForMode.get(mode).put(transfer.from, transfer)); + nLinkedStops.incrementAndGet(); + nTransfersTotal.addAndGet(distinctTransfers.size()); + } - //Keep lambda! A method-ref would causes incorrect class and line number to be logged - //noinspection Convert2MethodRef - progress.step(m -> LOG.info(m)); + //Keep lambda! A method-ref would causes incorrect class and line number to be logged + //noinspection Convert2MethodRef + progress.step(m -> LOG.info(m)); + } }); - timetableRepository.addAllTransfersByStops(transfersByStop); + timetableRepository.addAllTransfersByStops(transfersByStopForMode); LOG.info(progress.completeMessage()); LOG.info( diff --git a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java index a57299d96ab..bb829b28f7c 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java @@ -35,6 +35,7 @@ import org.opentripplanner.model.transfer.DefaultTransferService; import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitLayer; import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.TransitLayerUpdater; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.impl.DelegatingTransitAlertServiceImpl; import org.opentripplanner.routing.services.TransitAlertService; import org.opentripplanner.routing.util.ConcurrentPublished; @@ -98,7 +99,7 @@ public class TimetableRepository implements Serializable { private final Map serviceCodes = new HashMap<>(); - private final Multimap transfersByStop = HashMultimap.create(); + private final Map> transfersByStopForMode = new HashMap<>(); private SiteRepository siteRepository; private ZonedDateTime transitServiceStarts = LocalDate.MAX.atStartOfDay(ZoneId.systemDefault()); @@ -430,8 +431,11 @@ public Map getServiceCodes() { } /** Pre-generated transfers between all stops. */ - public Collection getTransfersByStop(StopLocation stop) { - return transfersByStop.get(stop); + public Collection getTransfersByStop(StreetMode mode, StopLocation stop) { + if (transfersByStopForMode.containsKey(mode)) { + return transfersByStopForMode.get(mode).get(stop); + } + return Collections.emptyList(); } public SiteRepository getSiteRepository() { @@ -519,9 +523,12 @@ public void setUpdaterManager(GraphUpdaterManager updaterManager) { this.updaterManager = updaterManager; } - public void addAllTransfersByStops(Multimap transfersByStop) { + public void addAllTransfersByStops(Map> transfersByStopForMode) { invalidateIndex(); - this.transfersByStop.putAll(transfersByStop); + transfersByStopForMode + .forEach((mode, transfersByStop) -> { + this.transfersByStopForMode.put(mode, HashMultimap.create(transfersByStop)); + }); } /**