diff --git a/.gitignore b/.gitignore index 8e30c76867..af4b5e8a58 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,10 @@ web/service/src/main/resources/application.properties web/service/newrelic/newrelic.yml processor/tests/bin + +.vscode/ +app/gui/bin/ +app/pkg/bin/ +processor/notices/bin/ +processor/notices/tests/bin/ +web/service/bin/ diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadata.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadata.java index 4872d07308..0039f3abd2 100644 --- a/main/src/main/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadata.java +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadata.java @@ -43,17 +43,21 @@ public class FeedMetadata { private final List> FILE_BASED_COMPONENTS = List.of( - new Pair<>("Pathways", GtfsPathway.FILENAME), + new Pair<>("Pathways (basic)", GtfsPathway.FILENAME), + new Pair<>("Pathways (extra)", GtfsPathway.FILENAME), new Pair<>("Transfers", GtfsTransfer.FILENAME), new Pair<>("Fares V1", GtfsFareAttribute.FILENAME), new Pair<>("Fare Products", GtfsFareProduct.FILENAME), new Pair<>("Shapes", GtfsShape.FILENAME), - new Pair<>("Frequency-Based Trip", GtfsFrequency.FILENAME), + new Pair<>("Frequencies", GtfsFrequency.FILENAME), new Pair<>("Feed Information", GtfsFeedInfo.FILENAME), new Pair<>("Attributions", GtfsAttribution.FILENAME), new Pair<>("Translations", GtfsTranslation.FILENAME), new Pair<>("Fare Media", GtfsFareMedia.FILENAME), - new Pair<>("Zone-Based Fares", GtfsStopArea.FILENAME)); + new Pair<>("Zone-Based Fares", GtfsArea.FILENAME), + new Pair<>("Transfer Fares", GtfsFareTransferRule.FILENAME), + new Pair<>("Time-Based Fares", GtfsTimeframe.FILENAME), + new Pair<>("Levels", GtfsLevel.FILENAME)); protected FeedMetadata() {} @@ -148,9 +152,14 @@ private void loadSpecFeaturesBasedOnFieldPresence(GtfsFeedContainer feedContaine loadLocationTypesComponent(feedContainer); loadTraversalTimeComponent(feedContainer); loadPathwayDirectionsComponent(feedContainer); + loadPathwayExtraComponent(feedContainer); loadBlocksComponent(feedContainer); loadRouteBasedFaresComponent(feedContainer); loadContinuousStopsComponent(feedContainer); + loadZoneBasedComponent(feedContainer); + loadTimeBasedFaresComponent(feedContainer); + loadTransferFaresComponent(feedContainer); + loadLevelsComponent(feedContainer); } private void loadContinuousStopsComponent(GtfsFeedContainer feedContainer) { @@ -178,15 +187,9 @@ private void loadRouteBasedFaresComponent(GtfsFeedContainer feedContainer) { specFeatures.put( "Route-Based Fares", hasAtLeastOneRecordForFields( - feedContainer, - GtfsFareLegRule.FILENAME, - List.of( - GtfsFareLegRule::hasFromAreaId, - (Function) GtfsFareLegRule::hasToAreaId)) - && hasAtLeastOneRecordForFields( - feedContainer, - GtfsRoute.FILENAME, - List.of((Function) GtfsRoute::hasNetworkId))); + feedContainer, + GtfsRoute.FILENAME, + List.of((Function) GtfsRoute::hasNetworkId))); } private void loadBlocksComponent(GtfsFeedContainer feedContainer) { @@ -209,6 +212,27 @@ private void loadPathwayDirectionsComponent(GtfsFeedContainer feedContainer) { (Function) GtfsPathway::hasReversedSignpostedAs))); } + private void loadPathwayExtraComponent(GtfsFeedContainer feedContainer) { + specFeatures.put( + "Pathway (extra)", + hasAtLeastOneRecordForFields( + feedContainer, + GtfsPathway.FILENAME, + List.of((Function) GtfsPathway::hasMaxSlope)) + || hasAtLeastOneRecordForFields( + feedContainer, + GtfsPathway.FILENAME, + List.of((Function) GtfsPathway::hasMinWidth)) + || hasAtLeastOneRecordForFields( + feedContainer, + GtfsPathway.FILENAME, + List.of((Function) GtfsPathway::hasLength)) + || hasAtLeastOneRecordForFields( + feedContainer, + GtfsPathway.FILENAME, + List.of((Function) GtfsPathway::hasStairCount))); + } + private void loadTraversalTimeComponent(GtfsFeedContainer feedContainer) { specFeatures.put( "Traversal Time", @@ -306,6 +330,25 @@ private void loadRouteNamesComponent(GtfsFeedContainer feedContainer) { (Function) GtfsRoute::hasRouteLongName))); } + private void loadZoneBasedComponent(GtfsFeedContainer feedContainer) { + specFeatures.put( + "Zone-Based Fares", hasAtLeastOneRecordInFile(feedContainer, GtfsArea.FILENAME)); + } + + private void loadTimeBasedFaresComponent(GtfsFeedContainer feedContainer) { + specFeatures.put( + "Time-Based Fares", hasAtLeastOneRecordInFile(feedContainer, GtfsTimeframe.FILENAME)); + } + + private void loadTransferFaresComponent(GtfsFeedContainer feedContainer) { + specFeatures.put( + "Transfer Fares", hasAtLeastOneRecordInFile(feedContainer, GtfsFareTransferRule.FILENAME)); + } + + private void loadLevelsComponent(GtfsFeedContainer feedContainer) { + specFeatures.put("Levels", hasAtLeastOneRecordInFile(feedContainer, GtfsLevel.FILENAME)); + } + private void loadAgencyData(GtfsTableContainer agencyTable) { for (GtfsAgency agency : agencyTable.getEntities()) { agencies.add(AgencyMetadata.from(agency)); diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidator.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidator.java index 8ac49b7b08..98dafc6a1a 100644 --- a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidator.java +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidator.java @@ -43,7 +43,6 @@ public class FareAttributeAgencyIdValidator extends FileValidator { @Override public void validate(NoticeContainer noticeContainer) { - // routes.agency_id is required when there are multiple agencies int totalAgencies = agencyTable.entityCount(); diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidator.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidator.java index 904b7cbcaa..b5e8b93960 100644 --- a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidator.java +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidator.java @@ -77,6 +77,7 @@ public void validate(NoticeContainer noticeContainer) { // A multilanguage feed may have different agency_lang. return; } + for (GtfsAgency agency : agencyTable.getEntities()) { if (agency.hasAgencyLang() && !feedLang.equals(agency.agencyLang())) { noticeContainer.addValidationNotice( diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidator.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidator.java index b3fdbf118e..d32d5d788e 100644 --- a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidator.java +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidator.java @@ -42,7 +42,6 @@ public class RouteAgencyIdValidator extends FileValidator { @Override public void validate(NoticeContainer noticeContainer) { - // routes.agency_id is required when there are multiple agencies int totalAgencies = agencyTable.entityCount(); diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java index 553e48a9a1..e173ea9ab5 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java @@ -227,7 +227,7 @@ public void containsPathwaysComponentTest() throws IOException, InterruptedExcep + "pathway2,stop2,stop3,2,0\n"; createDataFile("pathways.txt", pathwayContent); validateSpecFeature( - "Pathways", + "Pathways (basic)", true, ImmutableList.of(GtfsPathwayTableDescriptor.class, GtfsAgencyTableDescriptor.class)); } @@ -237,7 +237,7 @@ public void omitsPathwaysComponentTest() throws IOException, InterruptedExceptio String pathwayContent = "pathway_id,from_stop_id,to_stop_id,pathway_mode,is_bidirectional\n"; createDataFile("pathways.txt", pathwayContent); validateSpecFeature( - "Pathways", + "Pathways (basic)", false, ImmutableList.of(GtfsPathwayTableDescriptor.class, GtfsAgencyTableDescriptor.class)); } @@ -245,7 +245,7 @@ public void omitsPathwaysComponentTest() throws IOException, InterruptedExceptio @Test public void omitsComponents() throws IOException, InterruptedException { validateSpecFeature( - "Pathways", + "Pathways (basic)", false, ImmutableList.of(GtfsPathwayTableDescriptor.class, GtfsAgencyTableDescriptor.class)); validateSpecFeature( @@ -304,7 +304,7 @@ public void containsFrequencyBasedTripComponentTest() throws IOException, Interr "trip_id, start_time, end_time, headway_secs\n" + "dummy1, 01:01:01, 01:01:02, 1\n"; createDataFile(GtfsFrequency.FILENAME, content); validateSpecFeature( - "Frequency-Based Trip", + "Frequencies", true, ImmutableList.of(GtfsFrequencyTableDescriptor.class, GtfsAgencyTableDescriptor.class)); } @@ -314,7 +314,7 @@ public void omitsFrequencyBasedTripComponentTest() throws IOException, Interrupt String content = "trip_id, start_time, end_time, headway_secs\n"; createDataFile(GtfsFrequency.FILENAME, content); validateSpecFeature( - "Frequency-Based Trip", + "Frequencies", false, ImmutableList.of(GtfsFrequencyTableDescriptor.class, GtfsAgencyTableDescriptor.class)); } @@ -406,11 +406,11 @@ public void omitsFareMediaComponentTest() throws IOException, InterruptedExcepti @Test public void containsZoneBasedFaresComponentTest() throws IOException, InterruptedException { String content = "area_id, stop_id\n" + "dummyArea, dummyStop\n"; - createDataFile(GtfsStopArea.FILENAME, content); + createDataFile(GtfsArea.FILENAME, content); validateSpecFeature( "Zone-Based Fares", true, - ImmutableList.of(GtfsStopAreaTableDescriptor.class, GtfsAgencyTableDescriptor.class)); + ImmutableList.of(GtfsAreaTableDescriptor.class, GtfsAgencyTableDescriptor.class)); } @Test