Skip to content

Commit 03cd4dd

Browse files
authored
feat: separate out missing_prior_day_booking_field_value (#1996)
1 parent 0ca8740 commit 03cd4dd

File tree

10 files changed

+127
-59
lines changed

10 files changed

+127
-59
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.mobilitydata.gtfsvalidator.notice;
2+
3+
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice;
4+
5+
/**
6+
* The `prior_notice_last_day` value is required for prior day `booking_type` in booking_rules.txt.
7+
*/
8+
@GtfsValidationNotice(severity = SeverityLevel.ERROR)
9+
public class MissingPriorNoticeLastDayNotice extends ValidationNotice {
10+
/** The row number of the faulty record. */
11+
private final int csvRowNumber;
12+
13+
/** The `booking_rules.booking_rule_id` of the faulty record. */
14+
private final String bookingRuleId;
15+
16+
public MissingPriorNoticeLastDayNotice(int csvRowNumber, String bookingRuleId) {
17+
this.csvRowNumber = csvRowNumber;
18+
this.bookingRuleId = bookingRuleId;
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.mobilitydata.gtfsvalidator.notice;
2+
3+
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice;
4+
5+
/**
6+
* The `prior_notice_last_time` value is required for prior day `booking_type` in booking_rules.txt.
7+
*/
8+
@GtfsValidationNotice(severity = SeverityLevel.ERROR)
9+
public class MissingPriorNoticeLastTimeNotice extends ValidationNotice {
10+
/** The row number of the faulty record. */
11+
private final int csvRowNumber;
12+
13+
/** The `booking_rules.booking_rule_id` of the faulty record. */
14+
private final String bookingRuleId;
15+
16+
public MissingPriorNoticeLastTimeNotice(int csvRowNumber, String bookingRuleId) {
17+
this.csvRowNumber = csvRowNumber;
18+
this.bookingRuleId = bookingRuleId;
19+
}
20+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.mobilitydata.gtfsvalidator.notice.deprecated;
2+
3+
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice;
4+
import org.mobilitydata.gtfsvalidator.notice.MissingPriorNoticeLastDayNotice;
5+
import org.mobilitydata.gtfsvalidator.notice.MissingPriorNoticeLastTimeNotice;
6+
import org.mobilitydata.gtfsvalidator.notice.SeverityLevel;
7+
import org.mobilitydata.gtfsvalidator.notice.ValidationNotice;
8+
9+
/**
10+
* The `prior_notice_last_day` and the `prior_notice_last_time` values are required for prior day
11+
* `booking_type` in booking_rules.txt.
12+
*/
13+
@GtfsValidationNotice(
14+
severity = SeverityLevel.ERROR,
15+
deprecated = true,
16+
deprecationVersion = "7.0.0",
17+
deprecationReason =
18+
"Separated into `missing_prior_notice_last_day` and `missing_prior_notice_last_time` notices",
19+
replacementNotices = {
20+
MissingPriorNoticeLastDayNotice.class,
21+
MissingPriorNoticeLastTimeNotice.class
22+
})
23+
public class MissingPriorDayBookingFieldValueNotice extends ValidationNotice {
24+
/** The row number of the faulty record. */
25+
private final int csvRowNumber;
26+
27+
/** The `booking_rules.booking_rule_id` of the faulty record. */
28+
private final String bookingRuleId;
29+
30+
MissingPriorDayBookingFieldValueNotice(int csvRowNumber, String bookingRuleId) {
31+
this.csvRowNumber = csvRowNumber;
32+
this.bookingRuleId = bookingRuleId;
33+
}
34+
}

core/src/main/java/org/mobilitydata/gtfsvalidator/notice/deprecated/UnusedParentStationNotice.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
deprecated = true,
1717
deprecationVersion = "7.0.0",
1818
deprecationReason = "Renamed to `unused_station`",
19-
replacementNotice = UnusedStationNotice.class)
19+
replacementNotices = {UnusedStationNotice.class})
2020
class UnusedParentStationNotice extends ValidationNotice {
2121
/** The row number of the faulty record. */
2222
private final int csvRowNumber;

core/src/main/java/org/mobilitydata/gtfsvalidator/notice/schema/NoticeSchema.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.mobilitydata.gtfsvalidator.notice.schema;
22

3+
import java.util.List;
34
import java.util.Map;
45
import java.util.TreeMap;
56
import javax.annotation.Nullable;
@@ -57,10 +58,10 @@ public class NoticeSchema {
5758
@Nullable private String deprecationVersion;
5859

5960
/**
60-
* Replacement notice code for the deprecated notice. This field is only used if {@link
61-
* #deprecated} is true and the notice has a replacement.
61+
* Replacement notice codes for the deprecated notice. This field is only used if {@link
62+
* #deprecated} is true and the notice has replacements.
6263
*/
63-
@Nullable private String replacementNoticeCode;
64+
@Nullable private List<String> replacementNoticeCodes;
6465

6566
public NoticeSchema(String code, SeverityLevel severityLevel) {
6667
this.code = code;
@@ -135,11 +136,11 @@ public void setDeprecationVersion(@Nullable String deprecationVersion) {
135136
}
136137

137138
@Nullable
138-
public String getReplacementNoticeCode() {
139-
return replacementNoticeCode;
139+
public List<String> getReplacementNoticeCodes() {
140+
return replacementNoticeCodes;
140141
}
141142

142-
public void setReplacementNoticeCode(@Nullable String replacementNoticeCode) {
143-
this.replacementNoticeCode = replacementNoticeCode;
143+
public void setReplacementNoticeCodes(@Nullable List<String> replacementNoticeCodes) {
144+
this.replacementNoticeCodes = replacementNoticeCodes;
144145
}
145146
}

core/src/main/java/org/mobilitydata/gtfsvalidator/notice/schema/NoticeSchemaGenerator.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@
2626
import java.io.InputStreamReader;
2727
import java.io.Reader;
2828
import java.lang.reflect.Field;
29-
import java.util.Arrays;
30-
import java.util.List;
31-
import java.util.Map;
32-
import java.util.Optional;
33-
import java.util.TreeMap;
29+
import java.util.*;
3430
import java.util.logging.Level;
3531
import org.mobilitydata.gtfsvalidator.annotation.GtfsJson;
3632
import org.mobilitydata.gtfsvalidator.annotation.GtfsTable;
@@ -89,11 +85,17 @@ static NoticeSchema generateSchemaForNotice(Class<? extends Notice> noticeClass)
8985
schema.setDeprecationReason(noticeAnnotation.deprecationReason());
9086
schema.setDeprecationVersion(noticeAnnotation.deprecationVersion());
9187
// Validate that replacement notice is not Void.class and that it extends ValidationNotice
92-
if (noticeAnnotation.replacementNotice() != Void.class
93-
&& ValidationNotice.class.isAssignableFrom(noticeAnnotation.replacementNotice())) {
94-
String replacementNoticeCode =
95-
Notice.getCode(noticeAnnotation.replacementNotice().asSubclass(Notice.class));
96-
schema.setReplacementNoticeCode(replacementNoticeCode);
88+
List<String> replacementNotices = new ArrayList<>();
89+
for (Class<?> replacementNotice : noticeAnnotation.replacementNotices()) {
90+
if (replacementNotice == Void.class
91+
|| !ValidationNotice.class.isAssignableFrom(replacementNotice)) {
92+
continue;
93+
}
94+
String replacementNoticeCode = Notice.getCode(replacementNotice.asSubclass(Notice.class));
95+
replacementNotices.add(replacementNoticeCode);
96+
}
97+
if (!replacementNotices.isEmpty()) {
98+
schema.setReplacementNoticeCodes(replacementNotices);
9799
}
98100
}
99101
}

main/src/main/java/org/mobilitydata/gtfsvalidator/validator/BookingRulesEntityValidator.java

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice;
77
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice.FileRefs;
88
import org.mobilitydata.gtfsvalidator.annotation.GtfsValidator;
9-
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
10-
import org.mobilitydata.gtfsvalidator.notice.SeverityLevel;
11-
import org.mobilitydata.gtfsvalidator.notice.ValidationNotice;
9+
import org.mobilitydata.gtfsvalidator.notice.*;
1210
import org.mobilitydata.gtfsvalidator.table.GtfsBookingRules;
1311
import org.mobilitydata.gtfsvalidator.table.GtfsBookingRulesSchema;
1412
import org.mobilitydata.gtfsvalidator.table.GtfsBookingType;
@@ -60,9 +58,15 @@ private static void validatePriorNoticeDurationMin(
6058

6159
private static void validateMissingPriorDayBookingFields(
6260
GtfsBookingRules entity, NoticeContainer noticeContainer) {
63-
if (entity.bookingType() == GtfsBookingType.PRIORDAY
64-
&& (!entity.hasPriorNoticeLastDay() || !entity.hasPriorNoticeLastTime())) {
65-
noticeContainer.addValidationNotice(new MissingPriorDayBookingFieldValueNotice(entity));
61+
if (entity.bookingType() == GtfsBookingType.PRIORDAY) {
62+
if (!entity.hasPriorNoticeLastDay()) {
63+
noticeContainer.addValidationNotice(
64+
new MissingPriorNoticeLastDayNotice(entity.csvRowNumber(), entity.bookingRuleId()));
65+
}
66+
if (!entity.hasPriorNoticeLastTime()) {
67+
noticeContainer.addValidationNotice(
68+
new MissingPriorNoticeLastTimeNotice(entity.csvRowNumber(), entity.bookingRuleId()));
69+
}
6670
}
6771
}
6872

@@ -333,26 +337,6 @@ static class PriorNoticeLastDayAfterStartDayNotice extends ValidationNotice {
333337
}
334338
}
335339

336-
/**
337-
* `prior_notice_last_day` and `prior_notice_last_time` values are required for prior day
338-
* `booking_type` in booking_rules.txt.
339-
*/
340-
@GtfsValidationNotice(
341-
severity = SeverityLevel.ERROR,
342-
files = @FileRefs(GtfsBookingRulesSchema.class))
343-
static class MissingPriorDayBookingFieldValueNotice extends ValidationNotice {
344-
/** The row number of the faulty record. */
345-
private final int csvRowNumber;
346-
347-
/** The `booking_rules.booking_rule_id` of the faulty record. */
348-
private final String bookingRuleId;
349-
350-
MissingPriorDayBookingFieldValueNotice(GtfsBookingRules bookingRule) {
351-
this.csvRowNumber = bookingRule.csvRowNumber();
352-
this.bookingRuleId = bookingRule.bookingRuleId();
353-
}
354-
}
355-
356340
/**
357341
* `prior_notice_start_time` value is forbidden when `prior_notice_start_day` value is not set in
358342
* booking_rules.txt.

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import org.junit.Test;
88
import org.junit.runner.RunWith;
99
import org.junit.runners.JUnit4;
10+
import org.mobilitydata.gtfsvalidator.notice.MissingPriorNoticeLastDayNotice;
11+
import org.mobilitydata.gtfsvalidator.notice.MissingPriorNoticeLastTimeNotice;
1012
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
1113
import org.mobilitydata.gtfsvalidator.notice.ValidationNotice;
1214
import org.mobilitydata.gtfsvalidator.table.GtfsBookingRules;
@@ -214,10 +216,13 @@ public void missingPriorDayBookingFieldValueShouldGenerateNotice() {
214216
.setBookingRuleId("rule-11")
215217
.setBookingType(GtfsBookingType.PRIORDAY) // PRIORDAY booking type
216218
.build(); // No prior_notice_last_day or prior_notice_last_time set
217-
218-
assertThat(generateNotices(bookingRule))
219-
.containsExactly(
220-
new BookingRulesEntityValidator.MissingPriorDayBookingFieldValueNotice(bookingRule));
219+
List<ValidationNotice> expectedNotices =
220+
List.of(
221+
new MissingPriorNoticeLastDayNotice(
222+
bookingRule.csvRowNumber(), bookingRule.bookingRuleId()),
223+
new MissingPriorNoticeLastTimeNotice(
224+
bookingRule.csvRowNumber(), bookingRule.bookingRuleId()));
225+
assertThat(generateNotices(bookingRule)).containsExactlyElementsIn(expectedNotices);
221226

222227
// Case 2: Missing prior_notice_last_time only
223228
GtfsBookingRules bookingRuleMissingTime =
@@ -230,8 +235,8 @@ public void missingPriorDayBookingFieldValueShouldGenerateNotice() {
230235

231236
assertThat(generateNotices(bookingRuleMissingTime))
232237
.containsExactly(
233-
new BookingRulesEntityValidator.MissingPriorDayBookingFieldValueNotice(
234-
bookingRuleMissingTime));
238+
new MissingPriorNoticeLastTimeNotice(
239+
bookingRuleMissingTime.csvRowNumber(), bookingRuleMissingTime.bookingRuleId()));
235240

236241
// Case 3: Missing prior_notice_last_day only
237242
GtfsBookingRules bookingRuleMissingDay =
@@ -245,8 +250,8 @@ public void missingPriorDayBookingFieldValueShouldGenerateNotice() {
245250

246251
assertThat(generateNotices(bookingRuleMissingDay))
247252
.containsExactly(
248-
new BookingRulesEntityValidator.MissingPriorDayBookingFieldValueNotice(
249-
bookingRuleMissingDay));
253+
new MissingPriorNoticeLastDayNotice(
254+
bookingRuleMissingDay.csvRowNumber(), bookingRuleMissingDay.bookingRuleId()));
250255
}
251256

252257
@Test

model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/GtfsValidationNotice.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
String deprecationVersion() default "";
4141

4242
/**
43-
* Replacement notice class for the deprecated notice. This field is only used if {@link
44-
* #deprecated()} is true and the notice has a replacement.
43+
* Replacement notice classes for the deprecated notice. This field is only used if {@link
44+
* #deprecated()} is true and the notice has replacements.
4545
*/
46-
Class<?> replacementNotice() default Void.class;
46+
Class<?>[] replacementNotices() default {};
4747

4848
/**
4949
* GTFS specification section references. For specific file references, use {@link #files()}

web/client/src/routes/rules.html/+page.svelte

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,12 @@
234234
>
235235
{rule.deprecationVersion}
236236
</a></b>.
237-
{#if (rule.replacementNoticeCode)}
238-
It has been replaced by
239-
<code><a href="#{rule.replacementNoticeCode}-rule">{rule.replacementNoticeCode}</a></code>.
240-
{/if}
237+
{#if rule.replacementNoticeCodes}
238+
It has been replaced by
239+
{#each rule.replacementNoticeCodes as noticeCode, index}
240+
<code><a href="#{noticeCode}-rule">{noticeCode}</a></code>{index < rule.replacementNoticeCodes.length - 1 ? ', ' : '.'}
241+
{/each}
242+
{/if}
241243
<blockquote>
242244
<b>Deprecation reason:</b>
243245
{@html marked.parse(rule?.deprecationReason ?? '')}

0 commit comments

Comments
 (0)