return false;
} else {
LOG.trace("tripId {} found at index {} in scheduled timetable.", tripId, tripIndex);
}
TripTimes newTimes = new TripTimes(getTripTimes(tripIndex));
if (tripDescriptor.hasScheduleRelationship() && tripDescriptor.getScheduleRelationship()
== TripDescriptor.ScheduleRelationship.CANCELED) {
newTimes.cancel();
} else {
// The GTFS-RT reference specifies that StopTimeUpdates are sorted by stop_sequence.
Iterator<StopTimeUpdate> updates = tripUpdate.getStopTimeUpdateList().iterator();
if (!updates.hasNext()) {
LOG.warn("Won't apply zero-length trip update to trip {}.", tripId);
return false;
}
StopTimeUpdate update = updates.next();
int numStops = newTimes.getNumStops();
Integer delay = null;
for (int i = 0; i < numStops; i++) {
boolean match = false;
if (update != null) {
if (update.hasStopSequence()) {
match = update.getStopSequence() == newTimes.getStopSequence(i);
} else if (update.hasStopId()) {
match = pattern.getStop(i).getId().getId().equals(update.getStopId());
}
}
if (match) {
StopTimeUpdate.ScheduleRelationship scheduleRelationship =
update.hasScheduleRelationship() ? update.getScheduleRelationship()
: StopTimeUpdate.ScheduleRelationship.SCHEDULED;
if (scheduleRelationship == StopTimeUpdate.ScheduleRelationship.SKIPPED) {
// TODO: Handle partial trip cancellations
LOG.warn("Partially canceled trips are currently unsupported." +
" Skipping TripUpdate.");
return false;
} else if (scheduleRelationship ==
StopTimeUpdate.ScheduleRelationship.NO_DATA) {
newTimes.updateArrivalDelay(i, 0);
newTimes.updateDepartureDelay(i, 0);
delay = 0;
} else {
long today = updateServiceDate.getAsDate(timeZone).getTime() / 1000;
if (update.hasArrival()) {
StopTimeEvent arrival = update.getArrival();
if (arrival.hasDelay()) {
delay = arrival.getDelay();
if (arrival.hasTime()) {
newTimes.updateArrivalTime(i,
(int) (arrival.getTime() - today));
} else {
newTimes.updateArrivalDelay(i, delay);
}
} else if (arrival.hasTime()) {
newTimes.updateArrivalTime(i,
(int) (arrival.getTime() - today));
delay = newTimes.getArrivalDelay(i);
} else {
LOG.error("Arrival time at index {} is erroneous.", i);
return false;
}
} else {
if (delay == null) {
newTimes.updateArrivalTime(i, TripTimes.UNAVAILABLE);
} else {
newTimes.updateArrivalDelay(i, delay);
}
}
if (update.hasDeparture()) {
StopTimeEvent departure = update.getDeparture();
if (departure.hasDelay()) {
delay = departure.getDelay();
if (departure.hasTime()) {
newTimes.updateDepartureTime(i,
(int) (departure.getTime() - today));
} else {
newTimes.updateDepartureDelay(i, delay);
}
} else if (departure.hasTime()) {
newTimes.updateDepartureTime(i,
(int) (departure.getTime() - today));
delay = newTimes.getDepartureDelay(i);
} else {
LOG.error("Departure time at index {} is erroneous.", i);
return false;
}
} else {
if (delay == null) {
newTimes.updateDepartureTime(i, TripTimes.UNAVAILABLE);
} else {
newTimes.updateDepartureDelay(i, delay);
}
}
}
if (updates.hasNext()) {
update = updates.next();
} else {
update = null;
}
} else {
if (delay == null) {
newTimes.updateArrivalTime(i, TripTimes.UNAVAILABLE);
newTimes.updateDepartureTime(i, TripTimes.UNAVAILABLE);
} else {
newTimes.updateArrivalDelay(i, delay);
newTimes.updateDepartureDelay(i, delay);
}
}
}
if (update != null) {
LOG.error("Part of a TripUpdate object could not be applied successfully.");
return false;
}
}
if (!newTimes.timesIncreasing()) {
LOG.error("TripTimes are non-increasing after applying GTFS-RT delay propagation.");
return false;
}
// Update succeeded, save the new TripTimes back into this Timetable.