Skip to content

Commit 457aff0

Browse files
authored
Merge 2aa7bd2 into 9badbe8
2 parents 9badbe8 + 2aa7bd2 commit 457aff0

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package org.mobilitydata.gtfsvalidator.validator;
2+
3+
import static org.mobilitydata.gtfsvalidator.notice.SeverityLevel.ERROR;
4+
5+
import javax.inject.Inject;
6+
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice;
7+
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidator;
8+
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
9+
import org.mobilitydata.gtfsvalidator.notice.ValidationNotice;
10+
import org.mobilitydata.gtfsvalidator.table.*;
11+
import org.mobilitydata.gtfsvalidator.type.GtfsTime;
12+
13+
/**
14+
* Validates that if `routes.continuous_pickup` or `routes.continuous_drop_off` are included, then
15+
* `stop_times.start_pickup_drop_off_window` or `stop_times.end_pickup_drop_off_window` are not
16+
* defined for any trip of this route.
17+
*
18+
* <p>Generated notice: {@link ForbiddenContinuousPickupDropOffNotice}.
19+
*/
20+
@GtfsValidator
21+
public class ContinuousPickupDropOffValidator extends FileValidator {
22+
private final GtfsRouteTableContainer routeTable;
23+
private final GtfsTripTableContainer tripTable;
24+
private final GtfsStopTimeTableContainer stopTimeTable;
25+
26+
@Inject
27+
public ContinuousPickupDropOffValidator(
28+
GtfsRouteTableContainer routeTable,
29+
GtfsTripTableContainer tripTable,
30+
GtfsStopTimeTableContainer stopTimeTable) {
31+
this.routeTable = routeTable;
32+
this.tripTable = tripTable;
33+
this.stopTimeTable = stopTimeTable;
34+
}
35+
36+
@Override
37+
public void validate(NoticeContainer noticeContainer) {
38+
for (GtfsRoute route : routeTable.getEntities()) {
39+
boolean continuous =
40+
(route.continuousPickup() == GtfsContinuousPickupDropOff.ALLOWED
41+
|| route.continuousPickup() == GtfsContinuousPickupDropOff.MUST_PHONE
42+
|| route.continuousPickup() == GtfsContinuousPickupDropOff.ON_REQUEST_TO_DRIVER)
43+
|| (route.continuousDropOff() == GtfsContinuousPickupDropOff.ALLOWED
44+
|| route.continuousDropOff() == GtfsContinuousPickupDropOff.MUST_PHONE
45+
|| route.continuousDropOff() == GtfsContinuousPickupDropOff.ON_REQUEST_TO_DRIVER);
46+
if (!continuous) {
47+
continue;
48+
}
49+
for (GtfsTrip trip : tripTable.byRouteId(route.routeId())) {
50+
for (GtfsStopTime stopTime : stopTimeTable.byTripId(trip.tripId())) {
51+
if (stopTime.hasStartPickupDropOffWindow() || stopTime.hasEndPickupDropOffWindow()) {
52+
noticeContainer.addValidationNotice(
53+
new ForbiddenContinuousPickupDropOffNotice(
54+
route.csvRowNumber(),
55+
trip.tripId(),
56+
stopTime.startPickupDropOffWindow(),
57+
stopTime.endPickupDropOffWindow()));
58+
}
59+
}
60+
}
61+
}
62+
}
63+
64+
/**
65+
* Continuous pickup or drop-off are forbidden when routes.continuous_pickup or
66+
* routes.continuous_drop_off are 0, 2 or 3 and stop_times.start_pickup_drop_off_window or
67+
* stop_times.end_pickup_drop_off_window are defined for any trip of this route.
68+
*/
69+
@GtfsValidationNotice(severity = ERROR)
70+
public static class ForbiddenContinuousPickupDropOffNotice extends ValidationNotice {
71+
/** The row number of the route in the CSV file. */
72+
private final int routeCsvRowNumber;
73+
74+
/** The ID of the trip. */
75+
private final String tripId;
76+
77+
/** The start time of the pickup/drop-off window. */
78+
private final GtfsTime startPickupDropOffWindow;
79+
80+
/** The end time of the pickup/drop-off window. */
81+
private final GtfsTime endPickupDropOffWindow;
82+
83+
public ForbiddenContinuousPickupDropOffNotice(
84+
int routeCsvRowNumber,
85+
String tripId,
86+
GtfsTime startPickupDropOffWindow,
87+
GtfsTime endPickupDropOffWindow) {
88+
this.routeCsvRowNumber = routeCsvRowNumber;
89+
this.tripId = tripId;
90+
this.startPickupDropOffWindow = startPickupDropOffWindow;
91+
this.endPickupDropOffWindow = endPickupDropOffWindow;
92+
}
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package org.mobilitydata.gtfsvalidator.validator;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
5+
import java.util.List;
6+
import org.junit.Test;
7+
import org.junit.runner.RunWith;
8+
import org.junit.runners.JUnit4;
9+
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
10+
import org.mobilitydata.gtfsvalidator.notice.ValidationNotice;
11+
import org.mobilitydata.gtfsvalidator.table.*;
12+
import org.mobilitydata.gtfsvalidator.type.GtfsTime;
13+
14+
@RunWith(JUnit4.class)
15+
public class ContinuousPickupDropOffValidatorTest {
16+
17+
private static List<ValidationNotice> generateNotices(
18+
List<GtfsRoute> routes, List<GtfsTrip> trips, List<GtfsStopTime> stopTimes) {
19+
NoticeContainer noticeContainer = new NoticeContainer();
20+
GtfsRouteTableContainer routeTable =
21+
GtfsRouteTableContainer.forEntities(routes, noticeContainer);
22+
GtfsTripTableContainer tripTable = GtfsTripTableContainer.forEntities(trips, noticeContainer);
23+
GtfsStopTimeTableContainer stopTimeTable =
24+
GtfsStopTimeTableContainer.forEntities(stopTimes, noticeContainer);
25+
new ContinuousPickupDropOffValidator(routeTable, tripTable, stopTimeTable)
26+
.validate(noticeContainer);
27+
return noticeContainer.getValidationNotices();
28+
}
29+
30+
@Test
31+
public void continuousPickupWithPickupDropOffWindowShouldGenerateNotice() {
32+
List<ValidationNotice> notices =
33+
generateNotices(
34+
List.of(
35+
new GtfsRoute.Builder()
36+
.setCsvRowNumber(1)
37+
.setRouteId("route1")
38+
.setContinuousPickup(2)
39+
.build()),
40+
List.of(
41+
new GtfsTrip.Builder()
42+
.setCsvRowNumber(2)
43+
.setTripId("trip1")
44+
.setRouteId("route1")
45+
.build()),
46+
List.of(
47+
new GtfsStopTime.Builder()
48+
.setCsvRowNumber(3)
49+
.setTripId("trip1")
50+
.setStartPickupDropOffWindow(GtfsTime.fromString("08:00:00"))
51+
.setEndPickupDropOffWindow(GtfsTime.fromString("09:00:00"))
52+
.build()));
53+
assertThat(notices)
54+
.containsExactly(
55+
new ContinuousPickupDropOffValidator.ForbiddenContinuousPickupDropOffNotice(
56+
1, "trip1", GtfsTime.fromString("08:00:00"), GtfsTime.fromString("09:00:00")));
57+
}
58+
59+
@Test
60+
public void noContinuousPickupOrDropOffShouldNotGenerateNotice() {
61+
List<ValidationNotice> notices =
62+
generateNotices(
63+
List.of(new GtfsRoute.Builder().setCsvRowNumber(1).setRouteId("route1").build()),
64+
List.of(
65+
new GtfsTrip.Builder()
66+
.setCsvRowNumber(2)
67+
.setTripId("trip1")
68+
.setRouteId("route1")
69+
.build()),
70+
List.of(
71+
new GtfsStopTime.Builder()
72+
.setCsvRowNumber(3)
73+
.setTripId("trip1")
74+
.setStartPickupDropOffWindow(GtfsTime.fromString("08:00:00"))
75+
.build()));
76+
assertThat(notices).isEmpty();
77+
}
78+
79+
@Test
80+
public void continuousPickupAndDropOffWithoutPickupDropOffWindowShouldNotGenerateNotice() {
81+
List<ValidationNotice> notices =
82+
generateNotices(
83+
List.of(
84+
new GtfsRoute.Builder()
85+
.setCsvRowNumber(1)
86+
.setRouteId("route1")
87+
.setContinuousPickup(1)
88+
.setContinuousDropOff(1)
89+
.build()),
90+
List.of(
91+
new GtfsTrip.Builder()
92+
.setCsvRowNumber(2)
93+
.setTripId("trip1")
94+
.setRouteId("route1")
95+
.build()),
96+
List.of(new GtfsStopTime.Builder().setCsvRowNumber(3).setTripId("trip1").build()));
97+
assertThat(notices).isEmpty();
98+
}
99+
}

0 commit comments

Comments
 (0)