2
2
3
3
import java .util .ArrayList ;
4
4
import java .util .List ;
5
+ import java .util .function .Function ;
5
6
import org .mobilitydata .gtfsvalidator .annotation .GtfsValidationNotice ;
6
7
import org .mobilitydata .gtfsvalidator .annotation .GtfsValidationNotice .FileRefs ;
7
8
import org .mobilitydata .gtfsvalidator .annotation .GtfsValidator ;
@@ -17,97 +18,127 @@ public class BookingRulesEntityValidator extends SingleEntityValidator<GtfsBooki
17
18
18
19
@ Override
19
20
public void validate (GtfsBookingRules entity , NoticeContainer noticeContainer ) {
20
- validateForbiddenRealTimeFields (entity , noticeContainer );
21
- validateSameDayFields (entity , noticeContainer );
22
- validatePriorNotice (entity , noticeContainer );
21
+ validateBookingType (
22
+ entity ,
23
+ GtfsBookingType .REALTIME ,
24
+ BookingRulesEntityValidator ::findForbiddenRealTimeFields ,
25
+ ForbiddenRealTimeBookingFieldValueNotice ::new ,
26
+ noticeContainer );
27
+ validateBookingType (
28
+ entity ,
29
+ GtfsBookingType .SAMEDAY ,
30
+ BookingRulesEntityValidator ::findForbiddenSameDayFields ,
31
+ ForbiddenSameDayBookingFieldValueNotice ::new ,
32
+ noticeContainer );
33
+ validateBookingType (
34
+ entity ,
35
+ GtfsBookingType .PRIORDAY ,
36
+ BookingRulesEntityValidator ::findForbiddenPriorDayFields ,
37
+ ForbiddenPriorDayBookingFieldValueNotice ::new ,
38
+ noticeContainer );
39
+ validatePriorNoticeDurationMin (entity , noticeContainer );
40
+ validatePriorNoticeStartDay (entity , noticeContainer );
41
+ validatePriorNoticeDayRange (entity , noticeContainer );
23
42
}
24
43
25
- private void validatePriorNotice (GtfsBookingRules entity , NoticeContainer noticeContainer ) {
26
- if (entity .hasPriorNoticeLastDay ()
27
- && entity .hasPriorNoticeStartDay ()
28
- && entity .priorNoticeLastDay () > entity .priorNoticeStartDay ()) {
29
- noticeContainer .addValidationNotice (new PriorNoticeLastDayAfterStartDayNotice (entity ));
44
+ private static void validatePriorNoticeDurationMin (
45
+ GtfsBookingRules entity , NoticeContainer noticeContainer ) {
46
+ if (entity .hasPriorNoticeDurationMin () && entity .hasPriorNoticeDurationMax ()) {
47
+ if (entity .priorNoticeDurationMax () < entity .priorNoticeDurationMin ()) {
48
+ noticeContainer .addValidationNotice (
49
+ new InvalidPriorNoticeDurationMinNotice (
50
+ entity , entity .priorNoticeDurationMin (), entity .priorNoticeDurationMax ()));
51
+ }
30
52
}
31
53
}
32
54
33
- private static void validateForbiddenRealTimeFields (
55
+ private static void validatePriorNoticeStartDay (
34
56
GtfsBookingRules entity , NoticeContainer noticeContainer ) {
35
- // Only validate entities with REALTIME booking type
36
- if (entity .bookingType () != GtfsBookingType .REALTIME ) {
37
- return ;
38
- }
39
-
40
- // Retrieve the list of forbidden fields
41
- List <String > forbiddenFields = findForbiddenRealTimeFields (entity );
42
-
43
- // If there are any forbidden fields, add a validation notice
44
- if (!forbiddenFields .isEmpty ()) {
57
+ if (entity .hasPriorNoticeDurationMax () && entity .hasPriorNoticeStartDay ()) {
45
58
noticeContainer .addValidationNotice (
46
- new ForbiddenRealTimeBookingFieldValueNotice (entity , forbiddenFields ));
59
+ new ForbiddenPriorNoticeStartDayNotice (
60
+ entity , entity .priorNoticeStartDay (), entity .priorNoticeDurationMax ()));
47
61
}
48
62
}
49
63
50
- private static void validateSameDayFields (
51
- GtfsBookingRules entity , NoticeContainer noticeContainer ) {
52
- // Only validate entities with SAME_DAY booking type
53
- if (entity .bookingType () != GtfsBookingType .SAMEDAY ) {
64
+ private static void validateBookingType (
65
+ GtfsBookingRules entity ,
66
+ GtfsBookingType bookingType ,
67
+ Function <GtfsBookingRules , List <String >> forbiddenFieldsFinder ,
68
+ ValidationNoticeConstructor validationNoticeConstructor ,
69
+ NoticeContainer noticeContainer ) {
70
+
71
+ if (entity .bookingType () != bookingType ) {
54
72
return ;
55
73
}
56
74
57
- // Retrieve the list of forbidden fields
58
- List <String > forbiddenFields = findForbiddenSameDayFields (entity );
75
+ List <String > forbiddenFields = forbiddenFieldsFinder .apply (entity );
59
76
60
- // If there are any forbidden fields, add a validation notice
61
77
if (!forbiddenFields .isEmpty ()) {
62
78
noticeContainer .addValidationNotice (
63
- new ForbiddenSameDayBookingFieldValueNotice (entity , forbiddenFields ));
79
+ validationNoticeConstructor . create (entity , forbiddenFields ));
64
80
}
65
81
}
66
82
67
83
private static List <String > findForbiddenSameDayFields (GtfsBookingRules bookingRule ) {
68
- List <String > fields = new ArrayList <>();
84
+ return findForbiddenFields (
85
+ bookingRule .hasPriorNoticeLastDay (),
86
+ GtfsBookingRules .PRIOR_NOTICE_LAST_DAY_FIELD_NAME ,
87
+ bookingRule .hasPriorNoticeLastTime (),
88
+ GtfsBookingRules .PRIOR_NOTICE_LAST_TIME_FIELD_NAME ,
89
+ bookingRule .hasPriorNoticeServiceId (),
90
+ GtfsBookingRules .PRIOR_NOTICE_SERVICE_ID_FIELD_NAME );
91
+ }
69
92
70
- // Check each forbidden field and add its name to the list if it's present
71
- if (bookingRule .hasPriorNoticeLastDay ()) {
72
- fields .add (GtfsBookingRules .PRIOR_NOTICE_LAST_DAY_FIELD_NAME );
73
- }
74
- if (bookingRule .hasPriorNoticeLastTime ()) {
75
- fields .add (GtfsBookingRules .PRIOR_NOTICE_LAST_TIME_FIELD_NAME );
76
- }
77
- if (bookingRule .hasPriorNoticeServiceId ()) {
78
- fields .add (GtfsBookingRules .PRIOR_NOTICE_SERVICE_ID_FIELD_NAME );
79
- }
80
- return fields ;
93
+ private static List <String > findForbiddenPriorDayFields (GtfsBookingRules bookingRule ) {
94
+ return findForbiddenFields (
95
+ bookingRule .hasPriorNoticeDurationMin (),
96
+ GtfsBookingRules .PRIOR_NOTICE_DURATION_MIN_FIELD_NAME ,
97
+ bookingRule .hasPriorNoticeDurationMax (),
98
+ GtfsBookingRules .PRIOR_NOTICE_DURATION_MAX_FIELD_NAME );
81
99
}
82
100
83
- /** Finds forbidden fields that should not be present for real-time booking rules. */
84
- public static List <String > findForbiddenRealTimeFields (GtfsBookingRules bookingRule ) {
85
- List <String > fields = new ArrayList <>();
101
+ private static List <String > findForbiddenRealTimeFields (GtfsBookingRules bookingRule ) {
102
+ return findForbiddenFields (
103
+ bookingRule .hasPriorNoticeDurationMin (),
104
+ GtfsBookingRules .PRIOR_NOTICE_DURATION_MIN_FIELD_NAME ,
105
+ bookingRule .hasPriorNoticeDurationMax (),
106
+ GtfsBookingRules .PRIOR_NOTICE_DURATION_MAX_FIELD_NAME ,
107
+ bookingRule .hasPriorNoticeLastDay (),
108
+ GtfsBookingRules .PRIOR_NOTICE_LAST_DAY_FIELD_NAME ,
109
+ bookingRule .hasPriorNoticeLastTime (),
110
+ GtfsBookingRules .PRIOR_NOTICE_LAST_TIME_FIELD_NAME ,
111
+ bookingRule .hasPriorNoticeStartDay (),
112
+ GtfsBookingRules .PRIOR_NOTICE_START_DAY_FIELD_NAME ,
113
+ bookingRule .hasPriorNoticeStartTime (),
114
+ GtfsBookingRules .PRIOR_NOTICE_START_TIME_FIELD_NAME ,
115
+ bookingRule .hasPriorNoticeServiceId (),
116
+ GtfsBookingRules .PRIOR_NOTICE_SERVICE_ID_FIELD_NAME );
117
+ }
86
118
87
- // Check each forbidden field and add its name to the list if it's present
88
- if (bookingRule .hasPriorNoticeDurationMin ()) {
89
- fields .add (GtfsBookingRules .PRIOR_NOTICE_DURATION_MIN_FIELD_NAME );
90
- }
91
- if (bookingRule .hasPriorNoticeDurationMax ()) {
92
- fields .add (GtfsBookingRules .PRIOR_NOTICE_DURATION_MAX_FIELD_NAME );
93
- }
94
- if (bookingRule .hasPriorNoticeLastDay ()) {
95
- fields .add (GtfsBookingRules .PRIOR_NOTICE_LAST_DAY_FIELD_NAME );
96
- }
97
- if (bookingRule .hasPriorNoticeLastTime ()) {
98
- fields .add (GtfsBookingRules .PRIOR_NOTICE_LAST_TIME_FIELD_NAME );
99
- }
100
- if (bookingRule .hasPriorNoticeStartDay ()) {
101
- fields .add (GtfsBookingRules .PRIOR_NOTICE_START_DAY_FIELD_NAME );
102
- }
103
- if (bookingRule .hasPriorNoticeStartTime ()) {
104
- fields .add (GtfsBookingRules .PRIOR_NOTICE_START_TIME_FIELD_NAME );
119
+ private static List <String > findForbiddenFields (Object ... conditionsAndFields ) {
120
+ List <String > fields = new ArrayList <>();
121
+ for (int i = 0 ; i < conditionsAndFields .length ; i += 2 ) {
122
+ if ((Boolean ) conditionsAndFields [i ]) {
123
+ fields .add ((String ) conditionsAndFields [i + 1 ]);
124
+ }
105
125
}
106
- if (bookingRule .hasPriorNoticeServiceId ()) {
107
- fields .add (GtfsBookingRules .PRIOR_NOTICE_SERVICE_ID_FIELD_NAME );
126
+ return fields ;
127
+ }
128
+
129
+ private static void validatePriorNoticeDayRange (
130
+ GtfsBookingRules entity , NoticeContainer noticeContainer ) {
131
+ if (entity .hasPriorNoticeLastDay ()
132
+ && entity .hasPriorNoticeStartDay ()
133
+ && entity .priorNoticeLastDay () > entity .priorNoticeStartDay ()) {
134
+ noticeContainer .addValidationNotice (new PriorNoticeLastDayAfterStartDayNotice (entity ));
108
135
}
136
+ }
109
137
110
- return fields ;
138
+ // Abstract Notice Creation using Functional Interface
139
+ @ FunctionalInterface
140
+ private interface ValidationNoticeConstructor {
141
+ ValidationNotice create (GtfsBookingRules bookingRule , List <String > forbiddenFields );
111
142
}
112
143
113
144
/** A forbidden field value is present for a real-time booking rule in `booking_rules.txt`. */
@@ -154,6 +185,85 @@ static class ForbiddenSameDayBookingFieldValueNotice extends ValidationNotice {
154
185
}
155
186
}
156
187
188
+ /** A forbidden field value is present for a prior-day booking rule in `booking_rules.txt` */
189
+ @ GtfsValidationNotice (
190
+ severity = SeverityLevel .ERROR ,
191
+ files = @ FileRefs (GtfsBookingRulesSchema .class ))
192
+ static class ForbiddenPriorDayBookingFieldValueNotice extends ValidationNotice {
193
+ /** The row number of the faulty record. */
194
+ private final int csvRowNumber ;
195
+
196
+ /** The `booking_rules.booking_rule_id` of the faulty record. */
197
+ private final String bookingRuleId ;
198
+
199
+ /** The names of the forbidden fields comma-separated. */
200
+ private final String fieldNames ;
201
+
202
+ ForbiddenPriorDayBookingFieldValueNotice (
203
+ GtfsBookingRules bookingRule , List <String > forbiddenFields ) {
204
+ this .csvRowNumber = bookingRule .csvRowNumber ();
205
+ this .bookingRuleId = bookingRule .bookingRuleId ();
206
+ this .fieldNames = String .join (", " , forbiddenFields );
207
+ }
208
+ }
209
+
210
+ /**
211
+ * An invalid `prior_notice_duration_min` value is present in a booking rule.
212
+ *
213
+ * <p>The `prior_notice_duration_max` field value needs to be greater or equal to the
214
+ * `prior_notice_duration_min` field value.
215
+ */
216
+ @ GtfsValidationNotice (
217
+ severity = SeverityLevel .ERROR ,
218
+ files = @ FileRefs (GtfsBookingRulesSchema .class ))
219
+ static class InvalidPriorNoticeDurationMinNotice extends ValidationNotice {
220
+ /** The row number of the faulty record. */
221
+ private final int csvRowNumber ;
222
+
223
+ /** The `booking_rules.booking_rule_id` of the faulty record. */
224
+ private final String bookingRuleId ;
225
+
226
+ /** The value of the `prior_notice_duration_min` field. */
227
+ private final int priorNoticeDurationMin ;
228
+
229
+ /** The value of the `prior_notice_duration_max` field. */
230
+ private final int priorNoticeDurationMax ;
231
+
232
+ InvalidPriorNoticeDurationMinNotice (
233
+ GtfsBookingRules bookingRule , int priorNoticeDurationMin , int priorNoticeDurationMax ) {
234
+ this .csvRowNumber = bookingRule .csvRowNumber ();
235
+ this .bookingRuleId = bookingRule .bookingRuleId ();
236
+ this .priorNoticeDurationMin = priorNoticeDurationMin ;
237
+ this .priorNoticeDurationMax = priorNoticeDurationMax ;
238
+ }
239
+ }
240
+
241
+ /** `prior_notice_start_day` value is forbidden when `prior_notice_duration_max` is set. */
242
+ @ GtfsValidationNotice (
243
+ severity = SeverityLevel .ERROR ,
244
+ files = @ FileRefs (GtfsBookingRulesSchema .class ))
245
+ static class ForbiddenPriorNoticeStartDayNotice extends ValidationNotice {
246
+ /** The row number of the faulty record. */
247
+ private final int csvRowNumber ;
248
+
249
+ /** The `booking_rules.booking_rule_id` of the faulty record. */
250
+ private final String bookingRuleId ;
251
+
252
+ /** The value of the `prior_notice_duration_min` field. */
253
+ private final int priorNoticeStartDay ;
254
+
255
+ /** The value of the `prior_notice_duration_max` field. */
256
+ private final int priorNoticeDurationMax ;
257
+
258
+ ForbiddenPriorNoticeStartDayNotice (
259
+ GtfsBookingRules bookingRule , int priorNoticeStartDay , int priorNoticeDurationMax ) {
260
+ this .csvRowNumber = bookingRule .csvRowNumber ();
261
+ this .bookingRuleId = bookingRule .bookingRuleId ();
262
+ this .priorNoticeStartDay = priorNoticeStartDay ;
263
+ this .priorNoticeDurationMax = priorNoticeDurationMax ;
264
+ }
265
+ }
266
+
157
267
/**
158
268
* Prior notice last day should not be greater than the prior notice start day in
159
269
* booking_rules.txt.
0 commit comments