@@ -29,6 +29,14 @@ public boolean checkFieldsForMergeConflicts(Set<NewGTFSError> idErrors, FieldCon
29
29
return checkCalendarDatesIds (fieldContext );
30
30
}
31
31
32
+ @ Override
33
+ public void afterRowWrite () throws IOException {
34
+ // If the current row is for a calendar service_id that is marked for cloning/renaming, clone the
35
+ // values, change the ID, extend the start/end dates to the feed's full range, and write the
36
+ // additional line to the file.
37
+ addClonedServiceId ();
38
+ }
39
+
32
40
@ Override
33
41
public void startNewFeed (int feedIndex ) throws IOException {
34
42
super .startNewFeed (feedIndex );
@@ -37,6 +45,7 @@ public void startNewFeed(int feedIndex) throws IOException {
37
45
38
46
private boolean checkCalendarDatesIds (FieldContext fieldContext ) throws IOException {
39
47
boolean shouldSkipRecord = false ;
48
+ String key = getTableScopedValue (table , getIdScope (), keyValue );
40
49
// Drop any calendar_dates.txt records from the existing feed for dates that are
41
50
// not before the first date of the future feed.
42
51
LocalDate date = getCsvDate ("date" );
@@ -45,11 +54,37 @@ private boolean checkCalendarDatesIds(FieldContext fieldContext) throws IOExcept
45
54
"Skipping calendar_dates entry {} because it operates in the time span of future feed (i.e., after or on {})." ,
46
55
keyValue ,
47
56
futureFeedFirstDateForCalendarValidity );
48
- String key = getTableScopedValue (table , getIdScope (), keyValue );
49
57
mergeFeedsResult .skippedIds .add (key );
50
58
shouldSkipRecord = true ;
51
59
}
52
- // Track service ID because we want to avoid removing trips that may reference this
60
+
61
+ if (job .mergeType .equals (SERVICE_PERIOD )) {
62
+ if (isHandlingActiveFeed ()) {
63
+ // Remove calendar entries that are no longer used.
64
+ if (feedMergeContext .active .getServiceIdsToRemove ().contains (keyValue )) {
65
+ LOG .warn (
66
+ "Skipping active calendar entry {} because it will become unused in the merged feed." ,
67
+ keyValue );
68
+ mergeFeedsResult .skippedIds .add (key );
69
+ shouldSkipRecord = true ;
70
+ }
71
+ } else {
72
+ // If handling the future feed, the MTC revised feed merge logic is as follows:
73
+ // - Calendar entries from the future feed will be inserted as is in the merged feed.
74
+ // so no additional processing needed here, unless the calendar entry is no longer used,
75
+ // in that case we drop the calendar entry.
76
+ if (feedMergeContext .future .getServiceIdsToRemove ().contains (keyValue )) {
77
+ LOG .warn (
78
+ "Skipping future calendar entry {} because it will become unused in the merged feed." ,
79
+ keyValue );
80
+ mergeFeedsResult .skippedIds .add (key );
81
+ shouldSkipRecord = true ;
82
+ }
83
+ }
84
+ }
85
+
86
+
87
+ // Track service ID because we want to avoid removing trips that may reference this
53
88
// service_id when the service_id is used by calendar.txt records that operate in
54
89
// the valid date range, i.e., before the future feed's first date.
55
90
if (!shouldSkipRecord && fieldContext .nameEquals (SERVICE_ID )) mergeFeedsResult .serviceIds .add (fieldContext .getValueToWrite ());
@@ -75,4 +110,29 @@ private LocalDate getFutureFeedFirstDateForCheckingCalendarValidity() {
75
110
}
76
111
return futureFeedFirstDate ;
77
112
}
78
- }
113
+
114
+ /**
115
+ * Adds a cloned service id for trips with the same signature in both the active & future feeds.
116
+ * The cloned service id spans from the start date in the active feed until the end date in the future feed.
117
+ * @throws IOException
118
+ */
119
+ public void addClonedServiceId () throws IOException {
120
+ if (isHandlingFutureFeed () && job .mergeType .equals (SERVICE_PERIOD )) {
121
+ String originalServiceId = keyValue ;
122
+ if (job .serviceIdsToCloneRenameAndExtend .contains (originalServiceId )) {
123
+ String [] clonedValues = getOriginalRowValues ().clone ();
124
+ String newServiceId = clonedValues [keyFieldIndex ] = String .join (":" , getIdScope (), originalServiceId );
125
+
126
+ referenceTracker .checkReferencesAndUniqueness (
127
+ keyValue ,
128
+ getLineNumber (),
129
+ table .fields [0 ],
130
+ newServiceId ,
131
+ table ,
132
+ keyField ,
133
+ table .getOrderFieldName ()
134
+ );
135
+ writeValuesToTable (clonedValues , true );
136
+ }
137
+ }
138
+ }}
0 commit comments