Skip to content

Commit 3a579fe

Browse files
authored
Merge pull request #342 from conveyal/dev
Fix release January 7, 2022
2 parents 88dd9ea + f840040 commit 3a579fe

File tree

9 files changed

+87
-11
lines changed

9 files changed

+87
-11
lines changed

Diff for: src/main/java/com/conveyal/gtfs/loader/Feed.java

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public ValidationResult validate (FeedValidatorCreator... additionalValidators)
8787
List<FeedValidator> feedValidators = Lists.newArrayList(
8888
new MisplacedStopValidator(this, errorStorage, validationResult),
8989
new DuplicateStopsValidator(this, errorStorage),
90+
new ParentStationValidator(this, errorStorage),
9091
new FaresValidator(this, errorStorage),
9192
new FrequencyValidator(this, errorStorage),
9293
new TimeZoneValidator(this, errorStorage),

Diff for: src/main/java/com/conveyal/gtfs/loader/Table.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ public Table (String name, Class<? extends Entity> entityClass, Requirement requ
348348
new ShortField("drop_off_type", OPTIONAL, 3),
349349
new ShortField("continuous_pickup", OPTIONAL, 3),
350350
new ShortField("continuous_drop_off", OPTIONAL, 3),
351-
new DoubleField("shape_dist_traveled", OPTIONAL, 0, Double.POSITIVE_INFINITY, 2),
351+
new DoubleField("shape_dist_traveled", OPTIONAL, 0, Double.POSITIVE_INFINITY, -1),
352352
new ShortField("timepoint", OPTIONAL, 1),
353353
new IntegerField("fare_units_traveled", EXTENSION) // OpenOV NL extension
354354
).withParentTable(TRIPS);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.conveyal.gtfs.validator;
2+
3+
import com.conveyal.gtfs.error.NewGTFSError;
4+
import com.conveyal.gtfs.error.SQLErrorStorage;
5+
import com.conveyal.gtfs.loader.Feed;
6+
import com.conveyal.gtfs.loader.Table;
7+
import com.conveyal.gtfs.model.Stop;
8+
import com.google.common.collect.HashMultimap;
9+
import com.google.common.collect.Multimap;
10+
import com.google.common.collect.Sets;
11+
12+
import java.util.Collection;
13+
import java.util.HashSet;
14+
import java.util.Set;
15+
16+
import static com.conveyal.gtfs.error.NewGTFSErrorType.REFERENTIAL_INTEGRITY;
17+
18+
/**
19+
* Find stop#parent_station values that reference non-existent stop_ids. Unfortunately, we cannot perform this check
20+
* while the stops.txt table is being loaded because we do not yet have the full set of stop_ids available to check
21+
* parent_station values against.
22+
*/
23+
public class ParentStationValidator extends FeedValidator {
24+
25+
public ParentStationValidator(Feed feed, SQLErrorStorage errorStorage) {
26+
super(feed, errorStorage);
27+
}
28+
29+
@Override
30+
public void validate () {
31+
Multimap<String, Stop> stopsForParentStations = HashMultimap.create();
32+
Set<String> stopIds = new HashSet<>();
33+
for (Stop stop : feed.stops) {
34+
// Collect all stop_ids found in feed.
35+
stopIds.add(stop.stop_id);
36+
// Collect all non-null parent_station values.
37+
if (stop.parent_station != null) {
38+
stopsForParentStations.put(stop.parent_station, stop);
39+
}
40+
}
41+
// Find parent_station values that do not reference a valid stop_id from feed.
42+
Sets.SetView<String> badReferences = Sets.difference(stopsForParentStations.keySet(), stopIds);
43+
for (String parentStation : badReferences) {
44+
// For any bad parent_station ref (this could be more than one stop), add an error to the error storage.
45+
Collection<Stop> stops = stopsForParentStations.get(parentStation);
46+
for (Stop stop : stops) {
47+
registerError(
48+
NewGTFSError
49+
.forLine(Table.STOPS, stop.id, REFERENTIAL_INTEGRITY, parentStation)
50+
.setEntityId(stop.stop_id)
51+
);
52+
}
53+
}
54+
}
55+
56+
}

Diff for: src/test/java/com/conveyal/gtfs/GTFSTest.java

+9
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public void requiresActionCommand() throws Exception {
106106
public void canLoadAndExportSimpleAgency() {
107107
ErrorExpectation[] fakeAgencyErrorExpectations = ErrorExpectation.list(
108108
new ErrorExpectation(NewGTFSErrorType.MISSING_FIELD),
109+
new ErrorExpectation(NewGTFSErrorType.REFERENTIAL_INTEGRITY),
109110
new ErrorExpectation(NewGTFSErrorType.ROUTE_LONG_NAME_CONTAINS_SHORT_NAME),
110111
new ErrorExpectation(NewGTFSErrorType.FEED_TRAVEL_TIMES_ROUNDED),
111112
new ErrorExpectation(NewGTFSErrorType.STOP_UNUSED, equalTo("1234567")),
@@ -226,6 +227,7 @@ public void canLoadAndExportSimpleAgencyInSubDirectory() {
226227
new ErrorExpectation(NewGTFSErrorType.TABLE_IN_SUBDIRECTORY),
227228
new ErrorExpectation(NewGTFSErrorType.TABLE_IN_SUBDIRECTORY),
228229
new ErrorExpectation(NewGTFSErrorType.TABLE_IN_SUBDIRECTORY),
230+
new ErrorExpectation(NewGTFSErrorType.REFERENTIAL_INTEGRITY),
229231
new ErrorExpectation(NewGTFSErrorType.ROUTE_LONG_NAME_CONTAINS_SHORT_NAME),
230232
new ErrorExpectation(NewGTFSErrorType.FEED_TRAVEL_TIMES_ROUNDED),
231233
new ErrorExpectation(NewGTFSErrorType.STOP_UNUSED),
@@ -276,6 +278,13 @@ public void canLoadAndExportSimpleAgencyWithOnlyCalendarDates() {
276278
new RecordExpectation("shape_dist_traveled", 0.0, 0.01)
277279
}
278280
),
281+
// Check that the shape_dist_traveled values in stop_times are not rounded.
282+
new PersistenceExpectation(
283+
"stop_times",
284+
new RecordExpectation[]{
285+
new RecordExpectation("shape_dist_traveled", 341.4491961, 0.00001)
286+
}
287+
),
279288
new PersistenceExpectation(
280289
"trips",
281290
new RecordExpectation[]{

Diff for: src/test/resources/fake-agency/stops.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,locatio
33
johv,,Scotts Valley Dr & Victor Sq,,37.0590172,-122.0096058,,,0,,,
44
123,,Parent Station,,37.0666,-122.0777,,,1,,,
55
1234,,Child Stop,,37.06662,-122.07772,,,0,123,,
6-
1234567,,Unused stop,,37.06668,-122.07781,,,0,123,,
6+
1234567,,Unused stop,,37.06668,-122.07781,,,0,bad_stop_id_ref,,

Diff for: src/test/resources/snapshots/com/conveyal/gtfs/graphql/GTFSGraphQLTest/canFetchErrors-0.json

+17-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
"message" : "A required field was missing or empty in a particular row.",
1717
"priority" : "MEDIUM",
1818
"type" : "MISSING_FIELD"
19+
}, {
20+
"count" : 1,
21+
"message" : "This line references an ID that does not exist in the target table.",
22+
"priority" : "HIGH",
23+
"type" : "REFERENTIAL_INTEGRITY"
1924
}, {
2025
"count" : 1,
2126
"message" : "The long name of a route should complement the short name, not include it.",
@@ -35,36 +40,44 @@
3540
"error_id" : 0,
3641
"error_type" : "MISSING_FIELD",
3742
"line_number" : 2
43+
}, {
44+
"bad_value" : "bad_stop_id_ref",
45+
"entity_id" : "1234567",
46+
"entity_sequence" : null,
47+
"entity_type" : "Stop",
48+
"error_id" : 1,
49+
"error_type" : "REFERENTIAL_INTEGRITY",
50+
"line_number" : 6
3851
}, {
3952
"bad_value" : "route 1",
4053
"entity_id" : "1",
4154
"entity_sequence" : null,
4255
"entity_type" : "Route",
43-
"error_id" : 1,
56+
"error_id" : 2,
4457
"error_type" : "ROUTE_LONG_NAME_CONTAINS_SHORT_NAME",
4558
"line_number" : 2
4659
}, {
4760
"bad_value" : null,
4861
"entity_id" : null,
4962
"entity_sequence" : null,
5063
"entity_type" : null,
51-
"error_id" : 2,
64+
"error_id" : 3,
5265
"error_type" : "FEED_TRAVEL_TIMES_ROUNDED",
5366
"line_number" : null
5467
}, {
5568
"bad_value" : "1234567",
5669
"entity_id" : "1234567",
5770
"entity_sequence" : null,
5871
"entity_type" : "Stop",
59-
"error_id" : 3,
72+
"error_id" : 4,
6073
"error_type" : "STOP_UNUSED",
6174
"line_number" : 6
6275
}, {
6376
"bad_value" : "20170916",
6477
"entity_id" : null,
6578
"entity_sequence" : null,
6679
"entity_type" : null,
67-
"error_id" : 4,
80+
"error_id" : 5,
6881
"error_type" : "DATE_NO_SERVICE",
6982
"line_number" : null
7083
} ],

Diff for: src/test/resources/snapshots/com/conveyal/gtfs/graphql/GTFSGraphQLTest/canFetchFeedRowCounts-0.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"agency" : 1,
77
"calendar" : 1,
88
"calendar_dates" : 1,
9-
"errors" : 5,
9+
"errors" : 6,
1010
"routes" : 1,
1111
"stop_times" : 4,
1212
"stops" : 5,

Diff for: src/test/resources/snapshots/com/conveyal/gtfs/graphql/GTFSGraphQLTest/canFetchStopWithChildren-0.json

-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
"child_stops" : [ {
1515
"stop_id" : "1234",
1616
"stop_name" : "Child Stop"
17-
}, {
18-
"stop_id" : "1234567",
19-
"stop_name" : "Unused stop"
2017
} ],
2118
"stop_id" : "123",
2219
"stop_name" : "Parent Station"

Diff for: src/test/resources/snapshots/com/conveyal/gtfs/graphql/GTFSGraphQLTest/canFetchStops-0.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
}, {
108108
"id" : 6,
109109
"location_type" : 0,
110-
"parent_station" : "123",
110+
"parent_station" : "bad_stop_id_ref",
111111
"patterns" : [ ],
112112
"routes" : [ ],
113113
"stop_code" : null,

0 commit comments

Comments
 (0)