Skip to content

Commit c2bc785

Browse files
committed
Merge remote-tracking branch 'origin/fix-departureArrivalStopTime-npe' into fix-update-stale-service
# Conflicts: # application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java
2 parents 3a4753e + a7dc78e commit c2bc785

File tree

14 files changed

+597
-204
lines changed

14 files changed

+597
-204
lines changed

application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java

Lines changed: 46 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import graphql.schema.DataFetcher;
55
import graphql.schema.DataFetchingEnvironment;
66
import java.text.ParseException;
7-
import java.time.Instant;
87
import java.time.LocalDate;
98
import java.time.ZoneId;
109
import java.util.ArrayList;
@@ -13,6 +12,7 @@
1312
import java.util.List;
1413
import java.util.Optional;
1514
import java.util.stream.Collectors;
15+
import javax.annotation.Nullable;
1616
import org.locationtech.jts.geom.Geometry;
1717
import org.locationtech.jts.geom.LineString;
1818
import org.opentripplanner.apis.gtfs.GraphQLRequestContext;
@@ -23,7 +23,6 @@
2323
import org.opentripplanner.apis.gtfs.mapping.BikesAllowedMapper;
2424
import org.opentripplanner.apis.gtfs.model.TripOccupancy;
2525
import org.opentripplanner.apis.support.SemanticHash;
26-
import org.opentripplanner.model.Timetable;
2726
import org.opentripplanner.model.TripTimeOnDate;
2827
import org.opentripplanner.routing.alertpatch.EntitySelector;
2928
import org.opentripplanner.routing.alertpatch.TransitAlert;
@@ -36,7 +35,6 @@
3635
import org.opentripplanner.transit.model.site.StopLocation;
3736
import org.opentripplanner.transit.model.timetable.Direction;
3837
import org.opentripplanner.transit.model.timetable.Trip;
39-
import org.opentripplanner.transit.model.timetable.TripTimes;
4038
import org.opentripplanner.transit.service.TransitService;
4139
import org.opentripplanner.utils.time.ServiceDateUtils;
4240

@@ -132,38 +130,13 @@ public DataFetcher<Iterable<TransitAlert>> alerts() {
132130
@Override
133131
public DataFetcher<TripTimeOnDate> arrivalStoptime() {
134132
return environment -> {
135-
try {
136-
TransitService transitService = getTransitService(environment);
137-
TripPattern tripPattern = getTripPattern(environment);
138-
if (tripPattern == null) {
139-
return null;
140-
}
141-
Timetable timetable = tripPattern.getScheduledTimetable();
142-
143-
TripTimes triptimes = timetable.getTripTimes(getSource(environment));
144-
LocalDate serviceDate = null;
145-
Instant midnight = null;
146-
147-
var args = new GraphQLTypes.GraphQLTripArrivalStoptimeArgs(environment.getArguments());
148-
if (args.getGraphQLServiceDate() != null) {
149-
serviceDate = ServiceDateUtils.parseString(args.getGraphQLServiceDate());
150-
midnight =
151-
ServiceDateUtils
152-
.asStartOfService(serviceDate, transitService.getTimeZone())
153-
.toInstant();
154-
}
155-
156-
return new TripTimeOnDate(
157-
triptimes,
158-
triptimes.getNumStops() - 1,
159-
tripPattern,
160-
serviceDate,
161-
midnight
162-
);
163-
} catch (ParseException e) {
164-
//Invalid date format
165-
return null;
166-
}
133+
var serviceDate = getOptionalServiceDateArgument(environment);
134+
var trip = getSource(environment);
135+
var transitService = getTransitService(environment);
136+
var stopTimes = serviceDate
137+
.map(date -> transitService.getTripTimeOnDates(trip, date))
138+
.orElseGet(() -> transitService.getScheduledTripTimes(trip));
139+
return stopTimes.map(List::getLast).orElse(null);
167140
};
168141
}
169142

@@ -180,32 +153,13 @@ public DataFetcher<String> blockId() {
180153
@Override
181154
public DataFetcher<TripTimeOnDate> departureStoptime() {
182155
return environment -> {
183-
try {
184-
TransitService transitService = getTransitService(environment);
185-
TripPattern tripPattern = getTripPattern(environment);
186-
if (tripPattern == null) {
187-
return null;
188-
}
189-
Timetable timetable = tripPattern.getScheduledTimetable();
190-
191-
TripTimes triptimes = timetable.getTripTimes(getSource(environment));
192-
LocalDate serviceDate = null;
193-
Instant midnight = null;
194-
195-
var args = new GraphQLTypes.GraphQLTripDepartureStoptimeArgs(environment.getArguments());
196-
if (args.getGraphQLServiceDate() != null) {
197-
serviceDate = ServiceDateUtils.parseString(args.getGraphQLServiceDate());
198-
midnight =
199-
ServiceDateUtils
200-
.asStartOfService(serviceDate, transitService.getTimeZone())
201-
.toInstant();
202-
}
203-
204-
return new TripTimeOnDate(triptimes, 0, tripPattern, serviceDate, midnight);
205-
} catch (ParseException e) {
206-
//Invalid date format
207-
return null;
208-
}
156+
var serviceDate = getOptionalServiceDateArgument(environment);
157+
var trip = getSource(environment);
158+
var transitService = getTransitService(environment);
159+
var stopTimes = serviceDate
160+
.map(date -> transitService.getTripTimeOnDates(trip, date))
161+
.orElseGet(() -> transitService.getScheduledTripTimes(trip));
162+
return stopTimes.map(List::getFirst).orElse(null);
209163
};
210164
}
211165

@@ -300,43 +254,23 @@ public DataFetcher<Iterable<Object>> stops() {
300254

301255
@Override
302256
public DataFetcher<Iterable<TripTimeOnDate>> stoptimes() {
303-
return environment -> {
304-
TripPattern tripPattern = getTripPattern(environment);
305-
if (tripPattern == null) {
306-
return List.of();
307-
}
308-
return TripTimeOnDate.fromTripTimes(
309-
tripPattern.getScheduledTimetable(),
310-
getSource(environment)
311-
);
312-
};
257+
return environment ->
258+
getTransitService(environment).getScheduledTripTimes(getSource(environment)).orElse(null);
313259
}
314260

315261
@Override
316262
public DataFetcher<Iterable<TripTimeOnDate>> stoptimesForDate() {
317263
return environment -> {
318-
try {
319-
TransitService transitService = getTransitService(environment);
320-
Trip trip = getSource(environment);
321-
var args = new GraphQLTypes.GraphQLTripStoptimesForDateArgs(environment.getArguments());
322-
323-
ZoneId timeZone = transitService.getTimeZone();
324-
LocalDate serviceDate = args.getGraphQLServiceDate() != null
325-
? ServiceDateUtils.parseString(args.getGraphQLServiceDate())
326-
: LocalDate.now(timeZone);
327-
328-
TripPattern tripPattern = transitService.getPatternForTrip(trip, serviceDate);
329-
// no matching pattern found
330-
if (tripPattern == null) {
331-
return List.of();
332-
}
333-
334-
Instant midnight = ServiceDateUtils.asStartOfService(serviceDate, timeZone).toInstant();
335-
Timetable timetable = transitService.getTimetableForTripPattern(tripPattern, serviceDate);
336-
return TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight);
337-
} catch (ParseException e) {
338-
return null; // Invalid date format
339-
}
264+
TransitService transitService = getTransitService(environment);
265+
Trip trip = getSource(environment);
266+
var args = new GraphQLTypes.GraphQLTripStoptimesForDateArgs(environment.getArguments());
267+
268+
ZoneId timeZone = transitService.getTimeZone();
269+
LocalDate serviceDate = args.getGraphQLServiceDate() != null
270+
? ServiceDateUtils.parseString(args.getGraphQLServiceDate())
271+
: LocalDate.now(timeZone);
272+
273+
return transitService.getTripTimeOnDates(trip, serviceDate).orElse(null);
340274
};
341275
}
342276

@@ -400,6 +334,15 @@ private TripPattern getTripPattern(DataFetchingEnvironment environment) {
400334
return getTransitService(environment).getPatternForTrip(environment.getSource());
401335
}
402336

337+
private TripPattern getTripPattern(
338+
DataFetchingEnvironment environment,
339+
@Nullable LocalDate date
340+
) {
341+
return date == null
342+
? getTripPattern(environment)
343+
: getTransitService(environment).getPatternForTrip(environment.getSource(), date);
344+
}
345+
403346
private TransitService getTransitService(DataFetchingEnvironment environment) {
404347
return environment.<GraphQLRequestContext>getContext().transitService();
405348
}
@@ -408,6 +351,16 @@ private RealtimeVehicleService getRealtimeVehiclesService(DataFetchingEnvironmen
408351
return environment.<GraphQLRequestContext>getContext().realTimeVehicleService();
409352
}
410353

354+
private static Optional<LocalDate> getOptionalServiceDateArgument(
355+
DataFetchingEnvironment environment
356+
) throws ParseException {
357+
var args = new GraphQLTypes.GraphQLTripArrivalStoptimeArgs(environment.getArguments());
358+
if (args.getGraphQLServiceDate() != null) {
359+
return Optional.of(ServiceDateUtils.parseString(args.getGraphQLServiceDate()));
360+
}
361+
return Optional.empty();
362+
}
363+
411364
private Trip getSource(DataFetchingEnvironment environment) {
412365
return environment.getSource();
413366
}

application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/DatedServiceJourneyType.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import org.opentripplanner.apis.transmodel.model.framework.TransmodelDirectives;
1818
import org.opentripplanner.apis.transmodel.model.framework.TransmodelScalars;
1919
import org.opentripplanner.apis.transmodel.support.GqlUtil;
20-
import org.opentripplanner.routing.TripTimeOnDateHelper;
2120
import org.opentripplanner.transit.model.network.TripPattern;
2221
import org.opentripplanner.transit.model.site.StopLocation;
2322
import org.opentripplanner.transit.model.timetable.TripOnServiceDate;
@@ -152,11 +151,10 @@ public static GraphQLObjectType create(
152151
)
153152
.dataFetcher(environment -> {
154153
TripOnServiceDate tripOnServiceDate = tripOnServiceDate(environment);
155-
return TripTimeOnDateHelper.getTripTimeOnDates(
156-
GqlUtil.getTransitService(environment),
157-
tripOnServiceDate.getTrip(),
158-
tripOnServiceDate.getServiceDate()
159-
);
154+
return GqlUtil
155+
.getTransitService(environment)
156+
.getTripTimeOnDates(tripOnServiceDate.getTrip(), tripOnServiceDate.getServiceDate())
157+
.orElse(null);
160158
})
161159
.build()
162160
)

application/src/main/java/org/opentripplanner/apis/transmodel/model/timetable/ServiceJourneyType.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import org.opentripplanner.apis.transmodel.model.framework.TransmodelScalars;
2222
import org.opentripplanner.apis.transmodel.support.GqlUtil;
2323
import org.opentripplanner.framework.geometry.EncodedPolyline;
24-
import org.opentripplanner.model.TripTimeOnDate;
25-
import org.opentripplanner.routing.TripTimeOnDateHelper;
2624
import org.opentripplanner.transit.model.network.TripPattern;
2725
import org.opentripplanner.transit.model.site.StopLocation;
2826
import org.opentripplanner.transit.model.timetable.Trip;
@@ -235,14 +233,7 @@ public static GraphQLObjectType create(
235233
.description(
236234
"Returns scheduled passing times only - without real-time-updates, for realtime-data use 'estimatedCalls'"
237235
)
238-
.dataFetcher(env -> {
239-
Trip trip = trip(env);
240-
TripPattern tripPattern = GqlUtil.getTransitService(env).getPatternForTrip(trip);
241-
if (tripPattern == null) {
242-
return List.of();
243-
}
244-
return TripTimeOnDate.fromTripTimes(tripPattern.getScheduledTimetable(), trip);
245-
})
236+
.dataFetcher(env -> GqlUtil.getTransitService(env).getScheduledTripTimes(trip(env)))
246237
.build()
247238
)
248239
.field(
@@ -269,11 +260,10 @@ public static GraphQLObjectType create(
269260
.ofNullable(environment.getArgument("date"))
270261
.map(LocalDate.class::cast)
271262
.orElse(LocalDate.now(GqlUtil.getTransitService(environment).getTimeZone()));
272-
return TripTimeOnDateHelper.getTripTimeOnDates(
273-
GqlUtil.getTransitService(environment),
274-
trip(environment),
275-
serviceDate
276-
);
263+
return GqlUtil
264+
.getTransitService(environment)
265+
.getTripTimeOnDates(trip(environment), serviceDate)
266+
.orElse(null);
277267
})
278268
.build()
279269
)

application/src/main/java/org/opentripplanner/model/TripTimeOnDate.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import java.util.ArrayList;
66
import java.util.Comparator;
77
import java.util.List;
8+
import java.util.Objects;
9+
import javax.annotation.Nullable;
810
import org.opentripplanner.framework.i18n.I18NString;
911
import org.opentripplanner.transit.model.network.TripPattern;
1012
import org.opentripplanner.transit.model.site.StopLocation;
@@ -31,7 +33,10 @@ public class TripTimeOnDate {
3133
private final int stopIndex;
3234
// This is only needed because TripTimes has no reference to TripPattern
3335
private final TripPattern tripPattern;
36+
37+
@Nullable
3438
private final LocalDate serviceDate;
39+
3540
private final long midnight;
3641

3742
public TripTimeOnDate(TripTimes tripTimes, int stopIndex, TripPattern tripPattern) {
@@ -46,8 +51,8 @@ public TripTimeOnDate(
4651
TripTimes tripTimes,
4752
int stopIndex,
4853
TripPattern tripPattern,
49-
LocalDate serviceDate,
50-
Instant midnight
54+
@Nullable LocalDate serviceDate,
55+
@Nullable Instant midnight
5156
) {
5257
this.tripTimes = tripTimes;
5358
this.stopIndex = stopIndex;
@@ -59,9 +64,15 @@ public TripTimeOnDate(
5964
/**
6065
* Must pass in both Timetable and Trip, because TripTimes do not have a reference to
6166
* StopPatterns.
67+
*
68+
* @return null if the trip does not exist in the timetable
6269
*/
70+
@Nullable
6371
public static List<TripTimeOnDate> fromTripTimes(Timetable table, Trip trip) {
6472
TripTimes times = table.getTripTimes(trip);
73+
if (times == null) {
74+
return null;
75+
}
6576
List<TripTimeOnDate> out = new ArrayList<>();
6677
for (int i = 0; i < times.getNumStops(); ++i) {
6778
out.add(new TripTimeOnDate(times, i, table.getPattern()));
@@ -74,14 +85,20 @@ public static List<TripTimeOnDate> fromTripTimes(Timetable table, Trip trip) {
7485
* StopPatterns.
7586
*
7687
* @param serviceDate service day to set, if null none is set
88+
* @return null if the trip does not exist in the timetable
7789
*/
90+
91+
@Nullable
7892
public static List<TripTimeOnDate> fromTripTimes(
7993
Timetable table,
8094
Trip trip,
8195
LocalDate serviceDate,
8296
Instant midnight
8397
) {
8498
TripTimes times = table.getTripTimes(trip);
99+
if (times == null) {
100+
return null;
101+
}
85102
List<TripTimeOnDate> out = new ArrayList<>();
86103
for (int i = 0; i < times.getNumStops(); ++i) {
87104
out.add(new TripTimeOnDate(times, i, table.getPattern(), serviceDate, midnight));
@@ -270,4 +287,22 @@ public BookingInfo getPickupBookingInfo() {
270287
public BookingInfo getDropOffBookingInfo() {
271288
return tripTimes.getDropOffBookingInfo(stopIndex);
272289
}
290+
291+
@Override
292+
public boolean equals(Object o) {
293+
if (o == null || getClass() != o.getClass()) return false;
294+
TripTimeOnDate that = (TripTimeOnDate) o;
295+
return (
296+
stopIndex == that.stopIndex &&
297+
midnight == that.midnight &&
298+
Objects.equals(tripTimes, that.tripTimes) &&
299+
Objects.equals(tripPattern, that.tripPattern) &&
300+
Objects.equals(serviceDate, that.serviceDate)
301+
);
302+
}
303+
304+
@Override
305+
public int hashCode() {
306+
return Objects.hash(tripTimes, stopIndex, tripPattern, serviceDate, midnight);
307+
}
273308
}

0 commit comments

Comments
 (0)