Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception based scheduling #545

Merged
merged 15 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@
<groupId>com.github.conveyal</groupId>
<artifactId>gtfs-lib</artifactId>
<!-- Latest dev build on jitpack.io -->
<version>a3e5707</version>
<version>ba747df</version>
<!-- Exclusions added in order to silence SLF4J warnings about multiple bindings:
http://www.slf4j.org/codes.html#multiple_bindings
-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ private boolean checkCalendarDatesIds(FieldContext fieldContext) throws IOExcept
// the valid date range, i.e., before the future feed's first date.
if (!shouldSkipRecord && fieldContext.nameEquals(SERVICE_ID)) {
mergeFeedsResult.serviceIds.add(fieldContext.getValueToWrite());
mergeFeedsResult.calendarDatesServiceIds.add(fieldContext.getValueToWrite());
}

return !shouldSkipRecord;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ private boolean checkCalendarIds(Set<NewGTFSError> idErrors, FieldContext fieldC
// If service is going to be cloned, add to the output service ids.
if (!shouldSkipRecord && fieldContext.nameEquals(SERVICE_ID)) {
mergeFeedsResult.serviceIds.add(fieldContext.getValueToWrite());
mergeFeedsResult.calendarServiceIds.add(fieldContext.getValueToWrite());
}

return !shouldSkipRecord;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,21 @@ public class MergeFeedsResult implements Serializable {
/** Contains the set of IDs for records that were excluded in the merged feed */
public Set<String> skippedIds = new HashSet<>();
/**
* Track the set of service IDs to end up in the merged feed in order to determine which calendar_dates and trips
* records should be retained in the merged result.
* Track the set of service IDs to end up in the merged feed in order to determine which calendar, calendar_dates and
* trip records should be retained in the merged result.
*/
public Set<String> serviceIds = new HashSet<>();

/**
* Track the set of service IDs obtained from calendar records.
*/
public Set<String> calendarServiceIds = new HashSet<>();

/**
* Track the set of service IDs obtained from calendar date records.
*/
public Set<String> calendarDatesServiceIds = new HashSet<>();

/**
* Track the set of route IDs to end up in the merged feed in order to determine which route_attributes
* records should be retained in the merged result.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,75 @@ public void startNewRow() throws IOException {
.collect(Collectors.toList());
}

public enum ReferenceTableLookup {
TRIP_SERVICE_ID_KEY(
String.join(":", Table.TRIPS.name, SERVICE_ID, Table.CALENDAR.name, Table.CALENDAR_DATES.name)
);

private final String value;

ReferenceTableLookup(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public static ReferenceTableLookup fromValue(String key) {
for (ReferenceTableLookup ref: ReferenceTableLookup.values()) {
if (ref.getValue().equals(key)) {
return ref;
}
}
throw new UnsupportedOperationException(String.format("Unsupported reference table combination: %s.", key));
}
}

/**
* Determine which reference table to use. If there is only one reference use this. If there are multiple references
* determine the context and then the correct reference table to use.
*/
private Table getReferenceTable(FieldContext fieldContext, Field field) {
if (field.referenceTables.size() == 1) {
return field.referenceTables.iterator().next();
}

// A table reference is still required even if no match is found.
Table defaultTable = null;
switch (ReferenceTableLookup.fromValue(createKey(field))) {
case TRIP_SERVICE_ID_KEY:
boolean isCalendarServiceId = mergeFeedsResult.calendarServiceIds.contains(fieldContext.getValueToWrite());
boolean isCalendarDatesServiceId = mergeFeedsResult.calendarDatesServiceIds.contains(fieldContext.getValueToWrite());
if (isCalendarServiceId && !isCalendarDatesServiceId) {
return Table.CALENDAR;
} else if (!isCalendarServiceId && isCalendarDatesServiceId) {
return Table.CALENDAR_DATES;
} else {
// For this case it doesn't seem to matter which is returned so going with calendar.
defaultTable = Table.CALENDAR;
}
br648 marked this conversation as resolved.
Show resolved Hide resolved
// Add other cases as multiple references are added e.g. flex!.
}
return defaultTable;
}

/**
* Create a unique key for this table, field and reference tables.
*/
private String createKey(Field field) {
return String.format(
"%s:%s:%s",
table.name,
field.name,
field.referenceTables.stream().map(r -> r.name).collect(Collectors.joining(":"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully we don't rely extract values from keys by relying on the ":" separator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made changes to this in my latest update to use a more unque key.

);
}

public boolean checkForeignReferences(FieldContext fieldContext) throws IOException {
Field field = fieldContext.getField();
if (field.isForeignReference()) {
String key = getTableScopedValue(field.referenceTable, fieldContext.getValue());
String key = getTableScopedValue(getReferenceTable(fieldContext, field), fieldContext.getValue());
// Check if we're performing a service period merge, this ref field is a service_id, and it
// is not found in the list of service_ids (e.g., it was removed).
boolean isValidServiceId = mergeFeedsResult.serviceIds.contains(fieldContext.getValueToWrite());
Expand Down