Skip to content

Encapsulate transit model index #5973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -154,37 +154,33 @@ void testAddedTrip() {
assertEquals(SubMode.of(SUB_MODE), route.getNetexSubmode(), "submode should be mapped");
assertNotEquals(REPLACED_ROUTE, route, "Should not re-use replaced route");

// Assert transit model index
var transitModelIndex = TRANSIT_MODEL.getTransitModelIndex();
assertNotNull(transitModelIndex);
assertEquals(
route,
transitModelIndex.getRouteForId(TransitModelForTest.id(LINE_REF)),
transitService.getRouteForId(TransitModelForTest.id(LINE_REF)),
"Route should be added to transit index"
);
assertEquals(
trip,
transitModelIndex.getTripForId().get(TRIP_ID),
transitService.getTripForId(TRIP_ID),
"Route should be added to transit index"
);
var pattern = transitModelIndex.getPatternForTrip().get(trip);
var pattern = transitService.getPatternForTrip(trip);
assertNotNull(pattern);
assertEquals(route, pattern.getRoute());
assertTrue(
transitModelIndex
.getServiceCodesRunningForDate()
.get(SERVICE_DATE)
transitService
.getServiceCodesRunningForDate(SERVICE_DATE)
.contains(TRANSIT_MODEL.getServiceCodes().get(trip.getServiceId())),
"serviceId should be running on service date"
);
assertNotNull(
transitModelIndex.getTripOnServiceDateById().get(TRIP_ID),
transitService.getTripOnServiceDateById(TRIP_ID),
"TripOnServiceDate should be added to transit index by id"
);
assertNotNull(
transitModelIndex
.getTripOnServiceDateForTripAndDay()
.get(new TripIdAndServiceDate(TRIP_ID, SERVICE_DATE)),
transitService.getTripOnServiceDateForTripAndDay(
new TripIdAndServiceDate(TRIP_ID, SERVICE_DATE)
),
"TripOnServiceDate should be added to transit index for trip and day"
);

Expand Down Expand Up @@ -299,10 +295,7 @@ void testAddedTripOnAddedRoute() {
Route route = secondTrip.getRoute();
assertSame(firstTrip.getRoute(), route, "route be reused from the first trip");

// Assert transit model index
var transitModelIndex = TRANSIT_MODEL.getTransitModelIndex();
assertNotNull(transitModelIndex);
assertEquals(2, transitModelIndex.getPatternsForRoute().get(route).size());
assertEquals(2, transitService.getPatternsForRoute(route).size());

// Assert trip times
var times = secondAddedTrip.successValue().tripTimes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ public DirectTransferGenerator(
@Override
public void buildGraph() {
/* Initialize transit model index which is needed by the nearby stop finder. */
if (transitModel.getTransitModelIndex() == null) {
transitModel.index();
}
transitModel.index();

/* The linker will use streets if they are available, or straight-line distance otherwise. */
NearbyStopFinder nearbyStopFinder = createNearbyStopFinder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
import org.opentripplanner.routing.algorithm.raptoradapter.transit.Transfer;
import org.opentripplanner.transit.model.site.RegularStop;
import org.opentripplanner.transit.service.StopModel;
import org.opentripplanner.transit.service.TransitModel;
import org.opentripplanner.transit.service.TransitService;

class TransfersMapper {

/**
* Copy pre-calculated transfers from the original graph
* @return a list where each element is a list of transfers for the corresponding stop index
*/
static List<List<Transfer>> mapTransfers(StopModel stopModel, TransitModel transitModel) {
static List<List<Transfer>> mapTransfers(StopModel stopModel, TransitService transitService) {
List<List<Transfer>> transferByStopIndex = new ArrayList<>();

for (int i = 0; i < stopModel.stopIndexSize(); ++i) {
Expand All @@ -26,7 +26,7 @@ static List<List<Transfer>> mapTransfers(StopModel stopModel, TransitModel trans

ArrayList<Transfer> list = new ArrayList<>();

for (PathTransfer pathTransfer : transitModel.getTransfersByStop(stop)) {
for (PathTransfer pathTransfer : transitService.getTransfersByStop(stop)) {
if (pathTransfer.to instanceof RegularStop) {
int toStopIndex = pathTransfer.to.getIndex();
Transfer newTransfer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.site.StopTransferPriority;
import org.opentripplanner.transit.model.timetable.TripTimes;
import org.opentripplanner.transit.service.DefaultTransitService;
import org.opentripplanner.transit.service.StopModel;
import org.opentripplanner.transit.service.TransitModel;
import org.opentripplanner.transit.service.TransitService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -47,10 +49,12 @@ public class TransitLayerMapper {

private static final Logger LOG = LoggerFactory.getLogger(TransitLayerMapper.class);

private final TransitModel transitModel;
private final TransitService transitService;
private final StopModel stopModel;

private TransitLayerMapper(TransitModel transitModel) {
this.transitModel = transitModel;
this.transitService = new DefaultTransitService(transitModel);
this.stopModel = transitModel.getStopModel();
}

public static TransitLayer map(
Expand All @@ -74,20 +78,19 @@ private TransitLayer map(TransitTuningParameters tuningParameters) {
HashMap<LocalDate, List<TripPatternForDate>> tripPatternsByStopByDate;
List<List<Transfer>> transferByStopIndex;
ConstrainedTransfersForPatterns constrainedTransfers = null;
StopModel stopModel = transitModel.getStopModel();

LOG.info("Mapping transitLayer from TransitModel...");

Collection<TripPattern> allTripPatterns = transitModel.getAllTripPatterns();
Collection<TripPattern> allTripPatterns = transitService.getAllTripPatterns();

tripPatternsByStopByDate = mapTripPatterns(allTripPatterns);

transferByStopIndex = mapTransfers(stopModel, transitModel);
transferByStopIndex = mapTransfers(stopModel, transitService);

TransferIndexGenerator transferIndexGenerator = null;
if (OTPFeature.TransferConstraints.isOn()) {
transferIndexGenerator =
new TransferIndexGenerator(transitModel.getTransferService().listAll(), allTripPatterns);
new TransferIndexGenerator(transitService.getTransferService().listAll(), allTripPatterns);
constrainedTransfers = transferIndexGenerator.generateTransfers();
}

Expand All @@ -98,9 +101,9 @@ private TransitLayer map(TransitTuningParameters tuningParameters) {
return new TransitLayer(
tripPatternsByStopByDate,
transferByStopIndex,
transitModel.getTransferService(),
transitService.getTransferService(),
stopModel,
transitModel.getTimeZone(),
transitService.getTimeZone(),
transferCache,
constrainedTransfers,
transferIndexGenerator,
Expand All @@ -118,13 +121,10 @@ private HashMap<LocalDate, List<TripPatternForDate>> mapTripPatterns(
Collection<TripPattern> allTripPatterns
) {
TripPatternForDateMapper tripPatternForDateMapper = new TripPatternForDateMapper(
transitModel.getTransitModelIndex().getServiceCodesRunningForDate()
transitService.getServiceCodesRunningForDate()
);

Set<LocalDate> allServiceDates = transitModel
.getTransitModelIndex()
.getServiceCodesRunningForDate()
.keySet();
Set<LocalDate> allServiceDates = transitService.getAllServiceCodes();

List<TripPatternForDate> tripPatternForDates = Collections.synchronizedList(new ArrayList<>());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import gnu.trove.set.TIntSet;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -20,7 +19,7 @@
import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate;
import org.opentripplanner.transit.model.timetable.TripTimes;
import org.opentripplanner.transit.service.TransitModel;
import org.opentripplanner.transit.service.TransitEditorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -40,9 +39,7 @@ public class TransitLayerUpdater {

private static final Logger LOG = LoggerFactory.getLogger(TransitLayerUpdater.class);

private final TransitModel transitModel;

private final Map<LocalDate, TIntSet> serviceCodesRunningForDate;
private final TransitEditorService transitService;

/**
* Cache the TripPatternForDates indexed on the original TripPatterns in order to avoid this
Expand All @@ -58,31 +55,27 @@ public class TransitLayerUpdater {

private final Map<LocalDate, Set<TripPatternForDate>> tripPatternsRunningOnDateMapCache = new HashMap<>();

public TransitLayerUpdater(
TransitModel transitModel,
Map<LocalDate, TIntSet> serviceCodesRunningForDate
) {
this.transitModel = transitModel;
this.serviceCodesRunningForDate = serviceCodesRunningForDate;
public TransitLayerUpdater(TransitEditorService transitService) {
this.transitService = transitService;
}

public void update(
Set<Timetable> updatedTimetables,
Map<TripPattern, SortedSet<Timetable>> timetables
) {
if (!transitModel.hasRealtimeTransitLayer()) {
if (!transitService.hasRealtimeTransitLayer()) {
return;
}

long startTime = System.currentTimeMillis();

// Make a shallow copy of the realtime transit layer. Only the objects that are copied will be
// changed during this update process.
TransitLayer realtimeTransitLayer = new TransitLayer(transitModel.getRealtimeTransitLayer());
TransitLayer realtimeTransitLayer = new TransitLayer(transitService.getRealtimeTransitLayer());

// Instantiate a TripPatternForDateMapper with the new TripPattern mappings
TripPatternForDateMapper tripPatternForDateMapper = new TripPatternForDateMapper(
serviceCodesRunningForDate
transitService.getServiceCodesRunningForDate()
);

Set<LocalDate> datesToBeUpdated = new HashSet<>();
Expand Down Expand Up @@ -229,7 +222,7 @@ public void update(

// Switch out the reference with the updated realtimeTransitLayer. This is synchronized to
// guarantee that the reference is set after all the fields have been updated.
transitModel.setRealtimeTransitLayer(realtimeTransitLayer);
transitService.setRealtimeTransitLayer(realtimeTransitLayer);

LOG.debug(
"UPDATING {} tripPatterns took {} ms",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class TripPatternForDateMapper {
* @param serviceCodesRunningForDate - READ ONLY
*/
TripPatternForDateMapper(Map<LocalDate, TIntSet> serviceCodesRunningForDate) {
this.serviceCodesRunningForDate = Collections.unmodifiableMap(serviceCodesRunningForDate);
this.serviceCodesRunningForDate = serviceCodesRunningForDate;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.opentripplanner.standalone.server.OTPWebApplication;
import org.opentripplanner.street.model.StreetLimitationParameters;
import org.opentripplanner.street.model.elevation.ElevationUtils;
import org.opentripplanner.transit.service.DefaultTransitService;
import org.opentripplanner.transit.service.TransitModel;
import org.opentripplanner.updater.configure.UpdaterConfigurator;
import org.opentripplanner.visualizer.GraphVisualizer;
Expand Down Expand Up @@ -202,7 +203,7 @@ public static void creatTransitLayerForRaptor(
TransitModel transitModel,
TransitTuningParameters tuningParameters
) {
if (!transitModel.hasTransit() || transitModel.getTransitModelIndex() == null) {
if (!transitModel.hasTransit() || !transitModel.isIndexed()) {
LOG.warn(
"Cannot create Raptor data, that requires the graph to have transit data and be indexed."
);
Expand All @@ -211,10 +212,7 @@ public static void creatTransitLayerForRaptor(
transitModel.setTransitLayer(TransitLayerMapper.map(tuningParameters, transitModel));
transitModel.setRealtimeTransitLayer(new TransitLayer(transitModel.getTransitLayer()));
transitModel.setTransitLayerUpdater(
new TransitLayerUpdater(
transitModel,
transitModel.getTransitModelIndex().getServiceCodesRunningForDate()
)
new TransitLayerUpdater(new DefaultTransitService(transitModel))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -594,6 +595,16 @@ public void setTransitLayer(TransitLayer transitLayer) {
this.transitModel.setTransitLayer(transitLayer);
}

@Override
public void setRealtimeTransitLayer(TransitLayer realtimeTransitLayer) {
transitModel.setRealtimeTransitLayer(realtimeTransitLayer);
}

@Override
public boolean hasRealtimeTransitLayer() {
return transitModel.hasRealtimeTransitLayer();
}

@Override
public CalendarService getCalendarService() {
return this.transitModel.getCalendarService();
Expand Down Expand Up @@ -659,6 +670,16 @@ public Deduplicator getDeduplicator() {
return transitModel.getDeduplicator();
}

@Override
public Set<LocalDate> getAllServiceCodes() {
return Collections.unmodifiableSet(transitModelIndex.getServiceCodesRunningForDate().keySet());
}

@Override
public Map<LocalDate, TIntSet> getServiceCodesRunningForDate() {
return Collections.unmodifiableMap(transitModelIndex.getServiceCodesRunningForDate());
}

/**
* For each pattern visiting this {@link StopLocation} return its {@link TransitMode}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,22 @@ void addTripOnServiceDateForTripAndDay(

FeedScopedId getOrCreateServiceIdForDate(LocalDate serviceDate);

/**
* Set the original, immutable, transit layer,
* based on scheduled data (not real-time data).
*/
void setTransitLayer(TransitLayer transitLayer);

/**
* Return true if a real-time transit layer is present.
* The real-time transit layer is optional,
* it is present only when real-time updaters are configured.
*/
boolean hasRealtimeTransitLayer();

/**
* Publish the latest snapshot of the real-time transit layer.
* Should be called only when creating a new TransitLayer, from the graph writer thread.
*/
void setRealtimeTransitLayer(TransitLayer realtimeTransitLayer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -539,10 +539,15 @@ public void setHasScheduledService(boolean hasScheduledService) {
* The caller is responsible for calling the {@link #index()} method if it is a
* possibility that the index is not initialized (during graph build).
*/
public @Nullable TransitModelIndex getTransitModelIndex() {
@Nullable
TransitModelIndex getTransitModelIndex() {
return index;
}

public boolean isIndexed() {
return index != null;
}

public boolean hasFlexTrips() {
return !flexTripsById.isEmpty();
}
Expand Down
Loading
Loading