Skip to content

Commit e676228

Browse files
authored
Merge pull request #278 from conveyal/dev
Release
2 parents 94003ea + 7c0af2a commit e676228

24 files changed

+297
-104
lines changed

pom.xml

+4-13
Original file line numberDiff line numberDiff line change
@@ -205,15 +205,12 @@
205205
</build>
206206

207207
<repositories>
208-
<repository>
209-
<id>conveyal</id>
210-
<name>Conveyal Maven Repository</name>
211-
<url>https://maven.conveyal.com/</url>
212-
</repository>
213208
<repository>
214209
<id>osgeo</id>
215-
<name>Open Source Geospatial Foundation Repository</name>
216-
<url>http://download.osgeo.org/webdav/geotools/</url>
210+
<name>OSGeo Release Repository</name>
211+
<url>https://repo.osgeo.org/repository/release/</url>
212+
<snapshots><enabled>false</enabled></snapshots>
213+
<releases><enabled>true</enabled></releases>
217214
</repository>
218215
<!-- used for importing java projects from github -->
219216
<repository>
@@ -331,12 +328,6 @@
331328
<artifactId>commons-cli</artifactId>
332329
<version>1.4</version>
333330
</dependency>
334-
<!-- We should really find a way to do this without forking Jackson -->
335-
<dependency>
336-
<groupId>com.conveyal</groupId>
337-
<artifactId>jackson2-geojson</artifactId>
338-
<version>0.8</version>
339-
</dependency>
340331
<!-- JDBC support for Postgres databases. More modules would need to be added to access H2, SQLite etc. -->
341332
<dependency>
342333
<groupId>org.postgresql</groupId>

src/main/java/com/conveyal/gtfs/GTFS.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.conveyal.gtfs.loader.JdbcGtfsSnapshotter;
88
import com.conveyal.gtfs.loader.SnapshotResult;
99
import com.conveyal.gtfs.util.InvalidNamespaceException;
10+
import com.conveyal.gtfs.validator.FeedValidatorCreator;
1011
import com.conveyal.gtfs.validator.ValidationResult;
1112
import com.fasterxml.jackson.databind.ObjectMapper;
1213
import com.google.common.io.Files;
@@ -15,10 +16,10 @@
1516
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
1617
import org.apache.commons.dbcp2.PoolableConnectionFactory;
1718
import org.apache.commons.dbcp2.PoolingDataSource;
18-
import org.apache.commons.dbutils.DbUtils;
1919
import org.apache.commons.pool2.impl.GenericObjectPool;
2020
import org.slf4j.Logger;
2121
import org.slf4j.LoggerFactory;
22+
2223
import javax.sql.DataSource;
2324
import java.io.File;
2425
import java.io.IOException;
@@ -28,7 +29,6 @@
2829
import java.sql.PreparedStatement;
2930
import java.sql.ResultSet;
3031
import java.sql.SQLException;
31-
import java.sql.Statement;
3232

3333
import static com.conveyal.gtfs.util.Util.ensureValidNamespace;
3434

@@ -94,9 +94,9 @@ public static SnapshotResult makeSnapshot (String feedId, DataSource dataSource)
9494
/**
9595
* Once a feed has been loaded into the database, examine its contents looking for various problems and errors.
9696
*/
97-
public static ValidationResult validate (String feedId, DataSource dataSource) {
97+
public static ValidationResult validate (String feedId, DataSource dataSource, FeedValidatorCreator... additionalValidators) {
9898
Feed feed = new Feed(dataSource, feedId);
99-
ValidationResult result = feed.validate();
99+
ValidationResult result = feed.validate(additionalValidators);
100100
return result;
101101
}
102102

src/main/java/com/conveyal/gtfs/GTFSMain.java

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public static void main (String[] args) throws Exception {
3939

4040
if(cmd.hasOption("validate")) {
4141
feed.validate();
42+
// FIXME: See JsonManager.class for discussion about potential issues serializing GeoJSON.
4243
JsonManager<ValidationResult> json = new JsonManager(ValidationResult.class);
4344
ValidationResult result = new ValidationResult(arguments[0], feed);
4445
String resultString = json.writePretty(result);

src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java

+46-41
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,81 @@
33
import com.conveyal.gtfs.validator.model.Priority;
44

55
public enum NewGTFSErrorType {
6-
6+
// Standard errors.
7+
BOOLEAN_FORMAT(Priority.MEDIUM, "A GTFS boolean field must contain the value 1 or 0."),
8+
COLOR_FORMAT(Priority.MEDIUM, "A color should be specified with six-characters (three two-digit hexadecimal numbers)."),
9+
COLUMN_NAME_UNSAFE(Priority.HIGH, "Column header contains characters not safe in SQL, it was renamed."),
10+
CURRENCY_UNKNOWN(Priority.MEDIUM, "The currency code was not recognized."),
711
DATE_FORMAT(Priority.MEDIUM, "Date format should be YYYYMMDD."),
8-
DATE_RANGE(Priority.MEDIUM, "Date should is extremely far in the future or past."),
912
DATE_NO_SERVICE(Priority.MEDIUM, "No service_ids were active on a date within the range of dates with defined service."),
10-
TIME_FORMAT(Priority.MEDIUM, "Time format should be HH:MM:SS."),
11-
URL_FORMAT(Priority.MEDIUM, "URL format should be <scheme>://<authority><path>?<query>#<fragment>"),
12-
LANGUAGE_FORMAT(Priority.LOW, "Language should be specified with a valid BCP47 tag."),
13-
ILLEGAL_FIELD_VALUE(Priority.MEDIUM, "Fields may not contain tabs, carriage returns or new lines."),
14-
INTEGER_FORMAT(Priority.MEDIUM, "Incorrect integer format."),
15-
FARE_TRANSFER_MISMATCH(Priority.MEDIUM, "A fare that does not permit transfers has a non-zero transfer duration."),
16-
FREQUENCY_PERIOD_OVERLAP(Priority.MEDIUM, "A frequency for a trip overlaps with another frequency defined for the same trip."),
17-
FLOATING_FORMAT(Priority.MEDIUM, "Incorrect floating point number format."),
18-
COLUMN_NAME_UNSAFE(Priority.HIGH, "Column header contains characters not safe in SQL, it was renamed."),
19-
NUMBER_PARSING(Priority.MEDIUM, "Unable to parse number from value."),
20-
NUMBER_NEGATIVE(Priority.MEDIUM, "Number was expected to be non-negative."),
21-
NUMBER_TOO_SMALL(Priority.MEDIUM, "Number was below the allowed range."),
22-
NUMBER_TOO_LARGE(Priority.MEDIUM, "Number was above the allowed range."),
13+
DATE_RANGE(Priority.MEDIUM, "Date should is extremely far in the future or past."),
14+
DEPARTURE_BEFORE_ARRIVAL(Priority.MEDIUM, "The vehicle departs from this stop before it arrives."),
15+
DUPLICATE_HEADER(Priority.MEDIUM, "More than one column in a table had the same name in the header row."),
2316
DUPLICATE_ID(Priority.MEDIUM, "More than one entity in a table had the same ID."),
24-
DUPLICATE_TRIP(Priority.MEDIUM, "More than one trip had an identical schedule and stops."),
2517
DUPLICATE_STOP(Priority.MEDIUM, "More than one stop was located in exactly the same place."),
26-
DUPLICATE_HEADER(Priority.MEDIUM, "More than one column in a table had the same name in the header row."),
27-
MISSING_TABLE(Priority.MEDIUM, "This table is required by the GTFS specification but is missing."),
18+
DUPLICATE_TRIP(Priority.MEDIUM, "More than one trip had an identical schedule and stops."),
19+
FARE_TRANSFER_MISMATCH(Priority.MEDIUM, "A fare that does not permit transfers has a non-zero transfer duration."),
20+
FEED_TRAVEL_TIMES_ROUNDED(Priority.LOW, "All travel times in the feed are rounded to the minute, which may cause unexpected results in routing applications where travel times are zero."),
21+
FLOATING_FORMAT(Priority.MEDIUM, "Incorrect floating point number format."),
22+
FREQUENCY_PERIOD_OVERLAP(Priority.MEDIUM, "A frequency for a trip overlaps with another frequency defined for the same trip."),
23+
ILLEGAL_FIELD_VALUE(Priority.MEDIUM, "Fields may not contain tabs, carriage returns or new lines."),
24+
INTEGER_FORMAT(Priority.MEDIUM, "Incorrect integer format."),
25+
LANGUAGE_FORMAT(Priority.LOW, "Language should be specified with a valid BCP47 tag."),
26+
MISSING_ARRIVAL_OR_DEPARTURE(Priority.MEDIUM, "First and last stop times are required to have both an arrival and departure time."),
2827
MISSING_COLUMN(Priority.MEDIUM, "A required column was missing from a table."),
29-
MISSING_SHAPE(Priority.MEDIUM, "???"),
3028
MISSING_FIELD(Priority.MEDIUM, "A required field was missing or empty in a particular row."),
29+
MISSING_SHAPE(Priority.MEDIUM, "???"),
30+
MISSING_TABLE(Priority.MEDIUM, "This table is required by the GTFS specification but is missing."),
3131
MULTIPLE_SHAPES_FOR_PATTERN(Priority.MEDIUM, "Multiple shapes found for a single unique sequence of stops (i.e, trip pattern)."),
32-
WRONG_NUMBER_OF_FIELDS(Priority.MEDIUM, "A row did not have the same number of fields as there are headers in its table."),
3332
NO_SERVICE(Priority.HIGH, "There is no service defined on any day in this feed."),
33+
NUMBER_NEGATIVE(Priority.MEDIUM, "Number was expected to be non-negative."),
34+
NUMBER_PARSING(Priority.MEDIUM, "Unable to parse number from value."),
35+
NUMBER_TOO_LARGE(Priority.MEDIUM, "Number was above the allowed range."),
36+
NUMBER_TOO_SMALL(Priority.MEDIUM, "Number was below the allowed range."),
3437
OVERLAPPING_TRIP(Priority.MEDIUM, "Blocks?"),
35-
SHAPE_REVERSED(Priority.MEDIUM, "A shape appears to be intended for vehicles running the opposite direction on the route."),
36-
SHAPE_MISSING_COORDINATE(Priority.MEDIUM, "???"),
37-
TABLE_IN_SUBDIRECTORY(Priority.HIGH, "Rather than being at the root of the zip file, a table was nested in a subdirectory."),
38-
TABLE_MISSING_COLUMN_HEADERS(Priority.HIGH, "Table is missing column headers."),
39-
TABLE_TOO_LONG(Priority.MEDIUM, "Table is too long to record line numbers with a 32-bit integer, overflow will occur."),
40-
TIME_ZONE_FORMAT(Priority.MEDIUM, "Time zone format should match value from the Time Zone Database https://en.wikipedia.org/wiki/List_of_tz_database_time_zones."),
38+
REFERENTIAL_INTEGRITY(Priority.HIGH, "This line references an ID that does not exist in the target table."),
4139
REQUIRED_TABLE_EMPTY(Priority.MEDIUM, "This table is required by the GTFS specification but is empty."),
42-
FEED_TRAVEL_TIMES_ROUNDED(Priority.LOW, "All travel times in the feed are rounded to the minute, which may cause unexpected results in routing applications where travel times are zero."),
4340
ROUTE_DESCRIPTION_SAME_AS_NAME(Priority.LOW, "The description of a route is identical to its name, so does not add any information."),
4441
ROUTE_LONG_NAME_CONTAINS_SHORT_NAME(Priority.LOW, "The long name of a route should complement the short name, not include it."),
4542
ROUTE_SHORT_AND_LONG_NAME_MISSING(Priority.MEDIUM, "A route has neither a long nor a short name."),
4643
ROUTE_SHORT_NAME_TOO_LONG(Priority.MEDIUM, "The short name of a route is too long for display in standard GTFS consumer applications."),
44+
ROUTE_UNUSED(Priority.HIGH, "This route is defined but has no trips."),
4745
SERVICE_NEVER_ACTIVE(Priority.MEDIUM, "A service code was defined, but is never active on any date."),
4846
SERVICE_UNUSED(Priority.MEDIUM, "A service code was defined, but is never referenced by any trips."),
4947
SHAPE_DIST_TRAVELED_NOT_INCREASING(Priority.MEDIUM, "Shape distance traveled must increase with stop times."),
48+
SHAPE_MISSING_COORDINATE(Priority.MEDIUM, "???"),
49+
SHAPE_REVERSED(Priority.MEDIUM, "A shape appears to be intended for vehicles running the opposite direction on the route."),
5050
STOP_DESCRIPTION_SAME_AS_NAME(Priority.LOW, "The description of a stop is identical to its name, so does not add any information."),
51+
STOP_GEOGRAPHIC_OUTLIER(Priority.HIGH, "This stop is located very far from the middle 90% of stops in this feed."),
5152
STOP_LOW_POPULATION_DENSITY(Priority.HIGH, "A stop is located in a geographic area with very low human population density."),
5253
STOP_NAME_MISSING(Priority.MEDIUM, "A stop does not have a name."),
53-
STOP_GEOGRAPHIC_OUTLIER(Priority.HIGH, "This stop is located very far from the middle 90% of stops in this feed."),
5454
STOP_TIME_UNUSED(Priority.LOW, "This stop time allows neither pickup nor drop off and is not a timepoint, so it serves no purpose and should be removed from trip."),
5555
STOP_UNUSED(Priority.MEDIUM, "This stop is not referenced by any trips."),
56+
TABLE_IN_SUBDIRECTORY(Priority.HIGH, "Rather than being at the root of the zip file, a table was nested in a subdirectory."),
57+
TABLE_MISSING_COLUMN_HEADERS(Priority.HIGH, "Table is missing column headers."),
58+
TABLE_TOO_LONG(Priority.MEDIUM, "Table is too long to record line numbers with a 32-bit integer, overflow will occur."),
59+
TIME_FORMAT(Priority.MEDIUM, "Time format should be HH:MM:SS."),
60+
TIME_ZONE_FORMAT(Priority.MEDIUM, "Time zone format should match value from the Time Zone Database https://en.wikipedia.org/wiki/List_of_tz_database_time_zones."),
5661
TIMEPOINT_MISSING_TIMES(Priority.MEDIUM, "This stop time is marked as a timepoint, but is missing both arrival and departure times."),
62+
TRAVEL_DISTANCE_ZERO(Priority.MEDIUM, "The vehicle does not cover any distance between the last stop and this one."),
63+
TRAVEL_TIME_NEGATIVE(Priority.HIGH, "The vehicle arrives at this stop before it departs from the previous one."),
64+
TRAVEL_TIME_ZERO(Priority.HIGH, "The vehicle arrives at this stop at the same time it departs from the previous stop."),
65+
TRAVEL_TOO_FAST(Priority.MEDIUM, "The vehicle travels extremely fast to reach this stop from the previous one."),
66+
TRAVEL_TOO_SLOW(Priority.MEDIUM, "The vehicle is traveling very slowly to reach this stop from the previous one."),
5767
TRIP_EMPTY(Priority.HIGH, "This trip is defined but has no stop times."),
5868
TRIP_HEADSIGN_CONTAINS_ROUTE_NAME(Priority.LOW, "A trip headsign contains the route name, but should only contain information to distinguish it from other trips for the route."),
5969
TRIP_HEADSIGN_SHOULD_DESCRIBE_DESTINATION_OR_WAYPOINTS(Priority.LOW, "A trip headsign begins with 'to' or 'towards', but should begin with destination or direction and optionally include waypoints with 'via'"),
6070
TRIP_NEVER_ACTIVE(Priority.MEDIUM, "A trip is defined, but its service is never running on any date."),
61-
ROUTE_UNUSED(Priority.HIGH, "This route is defined but has no trips."),
62-
TRAVEL_DISTANCE_ZERO(Priority.MEDIUM, "The vehicle does not cover any distance between the last stop and this one."),
63-
TRAVEL_TIME_NEGATIVE(Priority.HIGH, "The vehicle arrives at this stop before it departs from the previous one."),
64-
TRAVEL_TIME_ZERO(Priority.HIGH, "The vehicle arrives at this stop at the same time it departs from the previous stop."),
65-
MISSING_ARRIVAL_OR_DEPARTURE(Priority.MEDIUM, "First and last stop times are required to have both an arrival and departure time."),
66-
TRIP_TOO_FEW_STOP_TIMES(Priority.MEDIUM, "A trip must have at least two stop times to represent travel."),
6771
TRIP_OVERLAP_IN_BLOCK(Priority.MEDIUM, "A trip overlaps another trip and shares the same block_id."),
68-
TRAVEL_TOO_SLOW(Priority.MEDIUM, "The vehicle is traveling very slowly to reach this stop from the previous one."),
69-
TRAVEL_TOO_FAST(Priority.MEDIUM, "The vehicle travels extremely fast to reach this stop from the previous one."),
72+
TRIP_TOO_FEW_STOP_TIMES(Priority.MEDIUM, "A trip must have at least two stop times to represent travel."),
73+
URL_FORMAT(Priority.MEDIUM, "URL format should be <scheme>://<authority><path>?<query>#<fragment>"),
7074
VALIDATOR_FAILED(Priority.HIGH, "The specified validation stage failed due to an error encountered during loading. This is likely due to an error encountered during loading (e.g., a date or number field is formatted incorrectly.)."),
71-
DEPARTURE_BEFORE_ARRIVAL(Priority.MEDIUM, "The vehicle departs from this stop before it arrives."),
72-
REFERENTIAL_INTEGRITY(Priority.HIGH, "This line references an ID that does not exist in the target table."),
73-
BOOLEAN_FORMAT(Priority.MEDIUM, "A GTFS boolean field must contain the value 1 or 0."),
74-
COLOR_FORMAT(Priority.MEDIUM, "A color should be specified with six-characters (three two-digit hexadecimal numbers)."),
75-
CURRENCY_UNKNOWN(Priority.MEDIUM, "The currency code was not recognized."),
75+
WRONG_NUMBER_OF_FIELDS(Priority.MEDIUM, "A row did not have the same number of fields as there are headers in its table."),
76+
77+
// MTC-specific errors.
78+
FIELD_VALUE_TOO_LONG(Priority.MEDIUM, "Field value has too many characters."),
79+
80+
// Unknown errors.
7681
OTHER(Priority.LOW, "Other errors.");
7782

7883
public final Priority priority;

0 commit comments

Comments
 (0)