diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/BidirectionalExitGateValidator.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/BidirectionalExitGateValidator.java new file mode 100644 index 0000000000..7fb3b3e2c2 --- /dev/null +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/validator/BidirectionalExitGateValidator.java @@ -0,0 +1,49 @@ +package org.mobilitydata.gtfsvalidator.validator; + +import static org.mobilitydata.gtfsvalidator.notice.SeverityLevel.ERROR; + +import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice; +import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice.FileRefs; +import org.mobilitydata.gtfsvalidator.annotation.GtfsValidator; +import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; +import org.mobilitydata.gtfsvalidator.notice.ValidationNotice; +import org.mobilitydata.gtfsvalidator.table.*; + +/** + * Validates that: + * + * + */ +@GtfsValidator +public class BidirectionalExitGateValidator extends SingleEntityValidator { + + @Override + public void validate(GtfsPathway entity, NoticeContainer noticeContainer) { + if (entity.pathwayMode().getNumber() == 7 && entity.isBidirectional().getNumber() == 1) { + noticeContainer.addValidationNotice(new BidirectionalExitGatesNotice(entity)); + } + } + + /** + * Pathway is bidirectional and has mode 7 (exit gate). + * + *

Exit gates (pathway_mode=7) must not be bidirectional. + */ + @GtfsValidationNotice(severity = ERROR, files = @FileRefs({GtfsPathwaySchema.class})) + static class BidirectionalExitGatesNotice extends ValidationNotice { + /** The row number of the validated record. */ + private final int csvRowNumber; + /** The pathway mode. */ + private final int pathwayMode; + /** Whether the pathway is bidirectional. */ + private final int isBidirectional; + + BidirectionalExitGatesNotice(GtfsPathway pathway) { + this.csvRowNumber = pathway.csvRowNumber(); + this.pathwayMode = pathway.pathwayMode().getNumber(); + this.isBidirectional = pathway.isBidirectional().getNumber(); + } + } +} diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BidirectionalExitGateValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BidirectionalExitGateValidatorTest.java new file mode 100644 index 0000000000..9945a99c83 --- /dev/null +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BidirectionalExitGateValidatorTest.java @@ -0,0 +1,42 @@ +package org.mobilitydata.gtfsvalidator.validator; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; +import org.mobilitydata.gtfsvalidator.table.GtfsPathway; +import org.mobilitydata.gtfsvalidator.table.GtfsPathwayIsBidirectional; + +@RunWith(JUnit4.class) +public class BidirectionalExitGateValidatorTest { + public static GtfsPathway createPathway( + int csvRowNumber, + Integer pathwayMode, + GtfsPathwayIsBidirectional gtfsPathwayIsBidirectional) { + return new GtfsPathway.Builder() + .setCsvRowNumber(csvRowNumber) + .setPathwayMode(pathwayMode) + .setIsBidirectional(gtfsPathwayIsBidirectional) + .build(); + } + + /** Tests that a pathway with bidirectional exit gates generates a notice. */ + @Test + public void isBidirectionalExitGateShouldGenerateNotice() { + GtfsPathway entity = createPathway(1, 7, GtfsPathwayIsBidirectional.BIDIRECTIONAL); + NoticeContainer noticeContainer = new NoticeContainer(); + new BidirectionalExitGateValidator().validate(entity, noticeContainer); + assertThat(noticeContainer.getValidationNotices()) + .containsExactly(new BidirectionalExitGateValidator.BidirectionalExitGatesNotice(entity)); + } + + @Test + public void isNotBidirectionalExitGateShouldNotGenerateNotice() { + GtfsPathway entity = createPathway(1, 7, GtfsPathwayIsBidirectional.UNIDIRECTIONAL); + NoticeContainer noticeContainer = new NoticeContainer(); + new BidirectionalExitGateValidator().validate(entity, noticeContainer); + assertThat(noticeContainer.getValidationNotices()).isEmpty(); + } +} diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeDocumentationTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeDocumentationTest.java index 37ad6656f4..57e8676441 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeDocumentationTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeDocumentationTest.java @@ -115,7 +115,7 @@ public void testThatNoticeFieldsAreDocumented() { .map(f -> f.getDeclaringClass().getSimpleName() + "." + f.getName()) .collect(Collectors.toList()); assertWithMessage( - "Every field of a validation notice much be documented with a JavaDoc comment (aka /** */, not //). The following fields are undocumented:") + "Every field of a validation notice must be documented with a JavaDoc comment (aka /** */, not //). The following fields are undocumented:") .that(fieldsWithoutComments) .isEmpty(); } diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeFieldsTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeFieldsTest.java index 6ed212c10e..6eab0628ec 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeFieldsTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NoticeFieldsTest.java @@ -195,7 +195,9 @@ public void testNoticeClassFieldNames() { "maxShapeDistanceTraveled", "maxTripDistanceTraveled", "fileNameA", - "fileNameB"); + "fileNameB", + "pathwayMode", + "isBidirectional"); } private static List discoverValidationNoticeFieldNames() {