Skip to content

Commit f0f1055

Browse files
authored
Merge 24924d2 into 5d17f67
2 parents 5d17f67 + 24924d2 commit f0f1055

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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 ContinuousPickupDropOffNotice}.
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.hasContinuousPickup()
41+
|| route.continuousPickup() != GtfsContinuousPickupDropOff.NOT_AVAILABLE)
42+
|| (route.hasContinuousDropOff()
43+
|| route.continuousDropOff() != GtfsContinuousPickupDropOff.NOT_AVAILABLE);
44+
if (!continuous) {
45+
continue;
46+
}
47+
for (GtfsTrip trip : tripTable.byRouteId(route.routeId())) {
48+
for (GtfsStopTime stopTime : stopTimeTable.byTripId(trip.tripId())) {
49+
if (stopTime.hasStartPickupDropOffWindow() || stopTime.hasEndPickupDropOffWindow()) {
50+
noticeContainer.addValidationNotice(
51+
new ContinuousPickupDropOffNotice(
52+
route.csvRowNumber(),
53+
trip.tripId(),
54+
stopTime.startPickupDropOffWindow(),
55+
stopTime.endPickupDropOffWindow()));
56+
}
57+
}
58+
}
59+
}
60+
}
61+
62+
/**
63+
* Continuous pickup or drop-off are forbidden when routes.continuous_pickup or
64+
* routes.continuous_drop_off are 2 or 3 and stop_times.start_pickup_drop_off_window or
65+
* stop_times.end_pickup_drop_off_window are defined for any trip of this route.
66+
*/
67+
@GtfsValidationNotice(severity = ERROR)
68+
public static class ContinuousPickupDropOffNotice extends ValidationNotice {
69+
/** The row number of the route in the CSV file. */
70+
private final int routeCsvRowNumber;
71+
72+
/** The ID of the trip. */
73+
private final String tripId;
74+
75+
/** The start time of the pickup/drop-off window. */
76+
private final GtfsTime startPickupDropOffWindow;
77+
78+
/** The end time of the pickup/drop-off window. */
79+
private final GtfsTime endPickupDropOffWindow;
80+
81+
public ContinuousPickupDropOffNotice(
82+
int routeCsvRowNumber,
83+
String tripId,
84+
GtfsTime startPickupDropOffWindow,
85+
GtfsTime endPickupDropOffWindow) {
86+
this.routeCsvRowNumber = routeCsvRowNumber;
87+
this.tripId = tripId;
88+
this.startPickupDropOffWindow = startPickupDropOffWindow;
89+
this.endPickupDropOffWindow = endPickupDropOffWindow;
90+
}
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
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(1)
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.ContinuousPickupDropOffNotice(
56+
1, "trip1", GtfsTime.fromString("08:00:00"), GtfsTime.fromString("09:00:00")));
57+
}
58+
59+
@Test
60+
public void continuousDropOffWithPickupDropOffWindowShouldGenerateNotice() {
61+
List<ValidationNotice> notices =
62+
generateNotices(
63+
List.of(
64+
new GtfsRoute.Builder()
65+
.setCsvRowNumber(1)
66+
.setRouteId("route1")
67+
.setContinuousDropOff(2)
68+
.build()),
69+
List.of(
70+
new GtfsTrip.Builder()
71+
.setCsvRowNumber(2)
72+
.setTripId("trip1")
73+
.setRouteId("route1")
74+
.build()),
75+
List.of(
76+
new GtfsStopTime.Builder()
77+
.setCsvRowNumber(3)
78+
.setTripId("trip1")
79+
.setStartPickupDropOffWindow(GtfsTime.fromString("08:00:00"))
80+
.setEndPickupDropOffWindow(GtfsTime.fromString("09:00:00"))
81+
.build()));
82+
assertThat(notices)
83+
.containsExactly(
84+
new ContinuousPickupDropOffValidator.ContinuousPickupDropOffNotice(
85+
1, "trip1", GtfsTime.fromString("08:00:00"), GtfsTime.fromString("09:00:00")));
86+
}
87+
88+
@Test
89+
public void noContinuousPickupOrDropOffShouldNotGenerateNotice() {
90+
List<ValidationNotice> notices =
91+
generateNotices(
92+
List.of(new GtfsRoute.Builder().setCsvRowNumber(1).setRouteId("route1").build()),
93+
List.of(
94+
new GtfsTrip.Builder()
95+
.setCsvRowNumber(2)
96+
.setTripId("trip1")
97+
.setRouteId("route1")
98+
.build()),
99+
List.of(
100+
new GtfsStopTime.Builder()
101+
.setCsvRowNumber(3)
102+
.setTripId("trip1")
103+
.setStartPickupDropOffWindow(GtfsTime.fromString("08:00:00"))
104+
.build()));
105+
assertThat(notices).isEmpty();
106+
}
107+
108+
@Test
109+
public void continuousPickupAndDropOffWithoutPickupDropOffWindowShouldNotGenerateNotice() {
110+
List<ValidationNotice> notices =
111+
generateNotices(
112+
List.of(
113+
new GtfsRoute.Builder()
114+
.setCsvRowNumber(1)
115+
.setRouteId("route1")
116+
.setContinuousPickup(1)
117+
.setContinuousDropOff(1)
118+
.build()),
119+
List.of(
120+
new GtfsTrip.Builder()
121+
.setCsvRowNumber(2)
122+
.setTripId("trip1")
123+
.setRouteId("route1")
124+
.build()),
125+
List.of(new GtfsStopTime.Builder().setCsvRowNumber(3).setTripId("trip1").build()));
126+
assertThat(notices).isEmpty();
127+
}
128+
}

main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeFieldsTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public void testNoticeClassFieldNames() {
8080
"departureTime1",
8181
"distanceKm",
8282
"endFieldName",
83+
"endPickupDropOffWindow",
8384
"endValue",
8485
"entityCount",
8586
"entityId",
@@ -182,6 +183,7 @@ public void testNoticeClassFieldNames() {
182183
"specifiedField",
183184
"speedKph",
184185
"startFieldName",
186+
"startPickupDropOffWindow",
185187
"startValue",
186188
"stopCsvRowNumber",
187189
"stopDesc",

0 commit comments

Comments
 (0)