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