diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java index 0b2eb2077b2..243ce6d1897 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java @@ -136,7 +136,7 @@ public DataFetcher arrivalStoptime() { var stopTimes = serviceDate .map(date -> transitService.getTripTimeOnDates(trip, date)) .orElseGet(() -> transitService.getScheduledTripTimes(trip)); - return stopTimes.getLast(); + return stopTimes.map(List::getLast).orElse(null); }; } @@ -159,7 +159,7 @@ public DataFetcher departureStoptime() { var stopTimes = serviceDate .map(date -> transitService.getTripTimeOnDates(trip, date)) .orElseGet(() -> transitService.getScheduledTripTimes(trip)); - return stopTimes.getFirst(); + return stopTimes.map(List::getFirst).orElse(null); }; } @@ -255,7 +255,7 @@ public DataFetcher> stops() { @Override public DataFetcher> stoptimes() { return environment -> - getTransitService(environment).getScheduledTripTimes(getSource(environment)); + getTransitService(environment).getScheduledTripTimes(getSource(environment)).orElse(null); } @Override @@ -270,7 +270,7 @@ public DataFetcher> stoptimesForDate() { ? ServiceDateUtils.parseString(args.getGraphQLServiceDate()) : LocalDate.now(timeZone); - return transitService.getTripTimeOnDates(trip, serviceDate); + return transitService.getTripTimeOnDates(trip, serviceDate).orElse(null); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/DatedServiceJourneyType.java b/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/DatedServiceJourneyType.java index 2bd9918680d..93458f01771 100644 --- a/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/DatedServiceJourneyType.java +++ b/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/DatedServiceJourneyType.java @@ -151,7 +151,8 @@ public static GraphQLObjectType create( TripOnServiceDate tripOnServiceDate = tripOnServiceDate(environment); return GqlUtil .getTransitService(environment) - .getTripTimeOnDates(tripOnServiceDate.getTrip(), tripOnServiceDate.getServiceDate()); + .getTripTimeOnDates(tripOnServiceDate.getTrip(), tripOnServiceDate.getServiceDate()) + .orElse(null); }) .build() ) diff --git a/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/ServiceJourneyType.java b/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/ServiceJourneyType.java index 1baa8ff6be9..2aeea5dbfba 100644 --- a/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/ServiceJourneyType.java +++ b/application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/ServiceJourneyType.java @@ -267,7 +267,8 @@ public static GraphQLObjectType create( .orElse(LocalDate.now(GqlUtil.getTransitService(environment).getTimeZone())); return GqlUtil .getTransitService(environment) - .getTripTimeOnDates(trip(environment), serviceDate); + .getTripTimeOnDates(trip(environment), serviceDate) + .orElse(null); }) .build() ) diff --git a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 2ecc29e3e63..0f2a0350f5e 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -8,7 +8,6 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -97,15 +96,17 @@ public DefaultTransitService( this.timetableSnapshot = timetableSnapshotBuffer; } - public List getScheduledTripTimes(Trip trip) { + public Optional> getScheduledTripTimes(Trip trip) { TripPattern tripPattern = getPatternForTrip(trip); if (tripPattern == null) { - return List.of(); + return Optional.empty(); } - return TripTimeOnDate.fromTripTimes(tripPattern.getScheduledTimetable(), trip); + return Optional.ofNullable( + TripTimeOnDate.fromTripTimes(tripPattern.getScheduledTimetable(), trip) + ); } - public List getTripTimeOnDates(Trip trip, LocalDate serviceDate) { + public Optional> getTripTimeOnDates(Trip trip, LocalDate serviceDate) { TripPattern pattern = getPatternForTrip(trip, serviceDate); Timetable timetable = getTimetableForTripPattern(pattern, serviceDate); @@ -123,12 +124,14 @@ public List getTripTimeOnDates(Trip trip, LocalDate serviceDate) // This check is made here to avoid changing TripTimeOnDate.fromTripTimes TripTimes times = timetable.getTripTimes(trip); if (!this.getServiceCodesRunningForDate(serviceDate).contains(times.getServiceCode())) { - return new ArrayList<>(); + return Optional.empty(); } else { Instant midnight = ServiceDateUtils .asStartOfService(serviceDate, this.getTimeZone()) .toInstant(); - return TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight); + return Optional.ofNullable( + TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight) + ); } } diff --git a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java index d8b7444581c..292fb59c786 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -64,9 +64,15 @@ * copy-on-write and shares a lot of objects with any other TransitLayer instances. */ public interface TransitService { - List getScheduledTripTimes(Trip trip); + /** + * @return empty if the trip doesn't exist in the timetable (e.g. real-time added) + */ + Optional> getScheduledTripTimes(Trip trip); - List getTripTimeOnDates(Trip trip, LocalDate serviceDate); + /** + * @return empty if the trip doesn't run on the date specified + */ + Optional> getTripTimeOnDates(Trip trip, LocalDate serviceDate); Collection getFeedIds(); diff --git a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 94b522db2d9..9b84ab1ee22 100644 --- a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -10,6 +10,7 @@ import java.time.LocalDate; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Set; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -46,8 +47,9 @@ class DefaultTransitServiceTest { private static final FeedScopedId SERVICE_ID = new FeedScopedId("FEED", "SERVICE"); private static final int SERVICE_CODE = 0; - private static final Trip TRIP = TimetableRepositoryForTest - .trip("REAL_TIME_TRIP") + private static final Trip TRIP = TimetableRepositoryForTest.trip("REAL_TIME_TRIP").build(); + private static final Trip ADDED_TRIP = TimetableRepositoryForTest + .trip("REAL_TIME_ADDED_TRIP") .withServiceId(SERVICE_ID) .build(); private static final ScheduledTripTimes SCHEDULED_TRIP_TIMES = ScheduledTripTimes @@ -76,6 +78,15 @@ class DefaultTransitServiceTest { .build(); private static final int DELAY = 120; private static final RealTimeTripTimes REALTIME_TRIP_TIMES = SCHEDULED_TRIP_TIMES.copyScheduledTimes(); + private static final RealTimeTripTimes ADDED_TRIP_TIMES = RealTimeTripTimes.of( + ScheduledTripTimes + .of() + .withTrip(ADDED_TRIP) + .withArrivalTimes(new int[] { 10, 11 }) + .withDepartureTimes(new int[] { 10, 11 }) + .withServiceCode(SERVICE_CODE) + .build() + ); static { for (var i = 0; i < REALTIME_TRIP_TIMES.getNumStops(); ++i) { @@ -110,6 +121,9 @@ static void setup() { timetableSnapshot.update( new RealTimeTripUpdate(REAL_TIME_PATTERN, REALTIME_TRIP_TIMES, SERVICE_DATE) ); + timetableSnapshot.update( + new RealTimeTripUpdate(REAL_TIME_PATTERN, ADDED_TRIP_TIMES, SERVICE_DATE) + ); return timetableSnapshot.commit(); }); @@ -160,9 +174,11 @@ void getPatternForStopsWithRealTime() { @Test void getScheduledTripTimes() { assertEquals( - List.of( - new TripTimeOnDate(SCHEDULED_TRIP_TIMES, 0, RAIL_PATTERN), - new TripTimeOnDate(SCHEDULED_TRIP_TIMES, 1, RAIL_PATTERN) + Optional.of( + List.of( + new TripTimeOnDate(SCHEDULED_TRIP_TIMES, 0, RAIL_PATTERN), + new TripTimeOnDate(SCHEDULED_TRIP_TIMES, 1, RAIL_PATTERN) + ) ), service.getScheduledTripTimes(TRIP) ); @@ -175,9 +191,11 @@ void getRealtimeTripTimes() { .toInstant(); assertEquals( - List.of( - new TripTimeOnDate(REALTIME_TRIP_TIMES, 0, REAL_TIME_PATTERN, SERVICE_DATE, midnight), - new TripTimeOnDate(REALTIME_TRIP_TIMES, 1, REAL_TIME_PATTERN, SERVICE_DATE, midnight) + Optional.of( + List.of( + new TripTimeOnDate(REALTIME_TRIP_TIMES, 0, REAL_TIME_PATTERN, SERVICE_DATE, midnight), + new TripTimeOnDate(REALTIME_TRIP_TIMES, 1, REAL_TIME_PATTERN, SERVICE_DATE, midnight) + ) ), service.getTripTimeOnDates(TRIP, SERVICE_DATE) ); @@ -185,6 +203,28 @@ void getRealtimeTripTimes() { @Test void getTripTimesOnNoServiceDay() { - assertEquals(List.of(), service.getTripTimeOnDates(TRIP, NO_SERVICE_DATE)); + assertEquals(Optional.empty(), service.getTripTimeOnDates(TRIP, NO_SERVICE_DATE)); + } + + @Test + void getScheduledTripTimesForAddedTrip() { + assertEquals(Optional.empty(), service.getScheduledTripTimes(ADDED_TRIP)); + } + + @Test + void getRealtimeTripTimesForAddedTrip() { + Instant midnight = ServiceDateUtils + .asStartOfService(SERVICE_DATE, service.getTimeZone()) + .toInstant(); + + assertEquals( + Optional.of( + List.of( + new TripTimeOnDate(ADDED_TRIP_TIMES, 0, REAL_TIME_PATTERN, SERVICE_DATE, midnight), + new TripTimeOnDate(ADDED_TRIP_TIMES, 1, REAL_TIME_PATTERN, SERVICE_DATE, midnight) + ) + ), + service.getTripTimeOnDates(ADDED_TRIP, SERVICE_DATE) + ); } }