diff --git a/src/main/java/org/opentripplanner/updater/trip/AddedStopTime.java b/src/main/java/org/opentripplanner/updater/trip/AddedStopTime.java index 093c8fbdf54..c1000b9c2ae 100644 --- a/src/main/java/org/opentripplanner/updater/trip/AddedStopTime.java +++ b/src/main/java/org/opentripplanner/updater/trip/AddedStopTime.java @@ -1,14 +1,10 @@ package org.opentripplanner.updater.trip; -import com.esotericsoftware.kryo.util.Null; import com.google.transit.realtime.GtfsRealtime; import de.mfdz.MfdzRealtimeExtensions; -import gnu.trove.set.hash.TIntHashSet; -import io.grpc.netty.shaded.io.netty.util.concurrent.ProgressivePromise; -import java.sql.Time; -import java.util.Objects; import java.util.Optional; -import java.util.concurrent.Future; +import java.util.OptionalInt; +import java.util.OptionalLong; import javax.annotation.Nullable; import org.opentripplanner.gtfs.mapping.PickDropMapper; import org.opentripplanner.model.PickDrop; @@ -19,113 +15,107 @@ */ final class AddedStopTime { - @Nullable - private final PickDrop pickup; + private final GtfsRealtime.TripUpdate.StopTimeUpdate stopTimeUpdate; - @Nullable - private final PickDrop dropOff; - - @Nullable - public final String stopId; + AddedStopTime(GtfsRealtime.TripUpdate.StopTimeUpdate stopTimeUpdate) { + this.stopTimeUpdate = stopTimeUpdate; + } - @Nullable - private final GtfsRealtime.TripUpdate.StopTimeEvent arrival; + PickDrop pickup() { + return getPickDrop( + getStopTimePropertiesExtension() + .map(MfdzRealtimeExtensions.StopTimePropertiesExtension::getPickupType) + .orElse(null) + ); + } - @Nullable - private final GtfsRealtime.TripUpdate.StopTimeEvent departure; + PickDrop dropOff() { + return getPickDrop( + getStopTimePropertiesExtension() + .map(MfdzRealtimeExtensions.StopTimePropertiesExtension::getDropoffType) + .orElse(null) + ); + } - @Nullable - public final Integer stopSequence; + private PickDrop getPickDrop( + @Nullable MfdzRealtimeExtensions.StopTimePropertiesExtension.DropOffPickupType extensionDropOffPickup + ) { + if (isSkipped()) { + return PickDrop.CANCELLED; + } - public final GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship scheduleRelationship; + if (extensionDropOffPickup == null) { + return toPickDrop(stopTimeUpdate.getScheduleRelationship()); + } - public static final PickDrop DEFAULT_PICK_DROP = PickDrop.SCHEDULED; + return PickDropMapper.map(extensionDropOffPickup.getNumber()); + } - AddedStopTime( - @Nullable PickDrop pickup, - @Nullable PickDrop dropOff, - @Nullable String stopId, - @Nullable GtfsRealtime.TripUpdate.StopTimeEvent arrival, - @Nullable GtfsRealtime.TripUpdate.StopTimeEvent departure, - @Nullable Integer stopSequence, - @Nullable GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship scheduleRelationship - ) { - this.pickup = pickup; - this.dropOff = dropOff; - this.stopId = stopId; - this.arrival = arrival; - this.departure = departure; - this.stopSequence = stopSequence; - this.scheduleRelationship = scheduleRelationship; + private Optional getStopTimePropertiesExtension() { + return stopTimeUpdate + .getStopTimeProperties() + .hasExtension(MfdzRealtimeExtensions.stopTimeProperties) + ? Optional.of( + stopTimeUpdate + .getStopTimeProperties() + .getExtension(MfdzRealtimeExtensions.stopTimeProperties) + ) + : Optional.empty(); } - PickDrop pickup() { - return Objects.requireNonNullElse(pickup, DEFAULT_PICK_DROP); + OptionalLong getArrivalTime() { + return stopTimeUpdate.hasArrival() + ? getTime(stopTimeUpdate.getArrival()) + : OptionalLong.empty(); } - PickDrop dropOff() { - return Objects.requireNonNullElse(dropOff, DEFAULT_PICK_DROP); + OptionalLong getDepartureTime() { + return stopTimeUpdate.hasDeparture() + ? getTime(stopTimeUpdate.getDeparture()) + : OptionalLong.empty(); } - @Nullable - Long getArrivalTime() { - if (arrival == null) { - return null; - } - return arrival.hasTime() ? arrival.getTime() : null; + private OptionalLong getTime(GtfsRealtime.TripUpdate.StopTimeEvent stopTimeEvent) { + return stopTimeEvent.hasTime() + ? OptionalLong.of(stopTimeEvent.getTime()) + : OptionalLong.empty(); } - @Nullable - Long getDepartureTime() { - if (departure == null) { - return null; - } - return departure.hasTime() ? departure.getTime() : null; + OptionalInt getArrivalDelay() { + return stopTimeUpdate.hasArrival() + ? getDelay(stopTimeUpdate.getArrival()) + : OptionalInt.empty(); } - @Nullable - Integer getArrivalDelay() { - if (arrival == null) { - return null; - } - return arrival.hasDelay() ? arrival.getDelay() : null; + OptionalInt getDepartureDelay() { + return stopTimeUpdate.hasDeparture() + ? getDelay(stopTimeUpdate.getDeparture()) + : OptionalInt.empty(); } - @Nullable - Integer getDepartureDelay() { - if (departure == null) { - return null; - } - return departure.hasDelay() ? departure.getDelay() : null; + private OptionalInt getDelay(GtfsRealtime.TripUpdate.StopTimeEvent stopTimeEvent) { + return stopTimeEvent.hasDelay() + ? OptionalInt.of(stopTimeEvent.getDelay()) + : OptionalInt.empty(); } - static AddedStopTime ofStopTime(GtfsRealtime.TripUpdate.StopTimeUpdate props) { - final var scheduleRelationship = props.getScheduleRelationship(); - var pickupType = toPickDrop(scheduleRelationship); - var dropOffType = pickupType; - if ( - scheduleRelationship != GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship.SKIPPED && - props.getStopTimeProperties().hasExtension(MfdzRealtimeExtensions.stopTimeProperties) - ) { - var ext = props - .getStopTimeProperties() - .getExtension(MfdzRealtimeExtensions.stopTimeProperties); - var pickup = ext.getPickupType(); - var dropOff = ext.getDropoffType(); - dropOffType = PickDropMapper.map(dropOff.getNumber()); - pickupType = PickDropMapper.map(pickup.getNumber()); - } - return new AddedStopTime( - pickupType, - dropOffType, - props.hasStopId() ? props.getStopId() : null, - props.hasArrival() ? props.getArrival() : null, - props.hasDeparture() ? props.getDeparture() : null, - props.hasStopSequence() ? props.getStopSequence() : null, - scheduleRelationship + boolean isSkipped() { + return ( + stopTimeUpdate.getScheduleRelationship() == + GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship.SKIPPED ); } + OptionalInt getStopSequence() { + return stopTimeUpdate.hasStopSequence() + ? OptionalInt.of(stopTimeUpdate.getStopSequence()) + : OptionalInt.empty(); + } + + Optional getStopId() { + return stopTimeUpdate.hasStopId() ? Optional.of(stopTimeUpdate.getStopId()) : Optional.empty(); + } + private static PickDrop toPickDrop( GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship scheduleRelationship ) { diff --git a/src/main/java/org/opentripplanner/updater/trip/TimetableSnapshotSource.java b/src/main/java/org/opentripplanner/updater/trip/TimetableSnapshotSource.java index 711aa10e783..f34c504efe8 100644 --- a/src/main/java/org/opentripplanner/updater/trip/TimetableSnapshotSource.java +++ b/src/main/java/org/opentripplanner/updater/trip/TimetableSnapshotSource.java @@ -531,11 +531,13 @@ private List checkNewStopTimeUpdatesAndFindStops( final List stops = new ArrayList<>(stopTimeUpdates.size()); for (int index = 0; index < stopTimeUpdates.size(); ++index) { - final var addedStopTime = AddedStopTime.ofStopTime(stopTimeUpdates.get(index)); + final var addedStopTime = new AddedStopTime(stopTimeUpdates.get(index)); // Check stop sequence - final var stopSequence = addedStopTime.stopSequence; - if (stopSequence != null) { + final var optionalStopSequence = addedStopTime.getStopSequence(); + if (optionalStopSequence.isPresent()) { + final var stopSequence = optionalStopSequence.getAsInt(); + // Check non-negative if (stopSequence < 0) { debug(tripId, "Trip update contains negative stop sequence, skipping."); @@ -553,8 +555,9 @@ private List checkNewStopTimeUpdatesAndFindStops( } // Find stops - final var stopId = addedStopTime.stopId; - if (stopId != null) { + final var optionalStopId = addedStopTime.getStopId(); + if (optionalStopId.isPresent()) { + final var stopId = optionalStopId.get(); // Find stop final var stop = transitEditorService.getRegularStop( new FeedScopedId(tripId.getFeedId(), stopId) @@ -573,13 +576,14 @@ private List checkNewStopTimeUpdatesAndFindStops( // Check arrival time final var arrival = addedStopTime.getArrivalTime(); - if (arrival != null) { + if (arrival.isPresent()) { + final var time = arrival.getAsLong(); // Check for increasing time - if (previousTime != null && previousTime > arrival) { + if (previousTime != null && previousTime > time) { debug(tripId, "Trip update contains decreasing times, skipping."); return null; } - previousTime = arrival; + previousTime = time; } else { debug(tripId, "Trip update misses arrival time, skipping."); return null; @@ -587,13 +591,14 @@ private List checkNewStopTimeUpdatesAndFindStops( // Check departure time final var departure = addedStopTime.getDepartureTime(); - if (departure != null) { + if (departure.isPresent()) { + final var time = departure.getAsLong(); // Check for increasing time - if (previousTime != null && previousTime > departure) { + if (previousTime != null && previousTime > time) { debug(tripId, "Trip update contains decreasing times, skipping."); return null; } - previousTime = departure; + previousTime = time; } else { debug(tripId, "Trip update misses departure time, skipping."); return null; @@ -768,7 +773,7 @@ private Result addTripToGraphAndBuffer( // Create StopTimes final List stopTimes = new ArrayList<>(stopTimeUpdates.size()); for (int index = 0; index < stopTimeUpdates.size(); ++index) { - final var added = AddedStopTime.ofStopTime(stopTimeUpdates.get(index)); + final var added = new AddedStopTime(stopTimeUpdates.get(index)); final var stop = stops.get(index); // Create stop time @@ -776,10 +781,10 @@ private Result addTripToGraphAndBuffer( stopTime.setTrip(trip); stopTime.setStop(stop); // Set arrival time - final var arrivalSecondsSinceEpoch = added.getArrivalTime(); - if (arrivalSecondsSinceEpoch != null) { - final int delay = Objects.requireNonNullElse(added.getArrivalDelay(), 0); - final long arrivalTime = arrivalSecondsSinceEpoch - midnightSecondsSinceEpoch - delay; + final var arrival = added.getArrivalTime(); + if (arrival.isPresent()) { + final var delay = added.getArrivalDelay().orElse(0); + final var arrivalTime = arrival.getAsLong() - midnightSecondsSinceEpoch - delay; if (arrivalTime < 0 || arrivalTime > MAX_ARRIVAL_DEPARTURE_TIME) { debug( trip.getId(), @@ -791,10 +796,10 @@ private Result addTripToGraphAndBuffer( stopTime.setArrivalTime((int) arrivalTime); } // Set departure time - final var departureSecondsSinceEpoch = added.getDepartureTime(); - if (departureSecondsSinceEpoch != null) { - final int delay = Objects.requireNonNullElse(added.getDepartureDelay(), 0); - final long departureTime = departureSecondsSinceEpoch - midnightSecondsSinceEpoch - delay; + final var departure = added.getDepartureTime(); + if (departure.isPresent()) { + final var delay = added.getDepartureDelay().orElse(0); + final long departureTime = departure.getAsLong() - midnightSecondsSinceEpoch - delay; if (departureTime < 0 || departureTime > MAX_ARRIVAL_DEPARTURE_TIME) { debug( trip.getId(), @@ -806,9 +811,7 @@ private Result addTripToGraphAndBuffer( stopTime.setDepartureTime((int) departureTime); } stopTime.setTimepoint(1); // Exact time - if (added.stopSequence != null) { - stopTime.setStopSequence(added.stopSequence); - } + added.getStopSequence().ifPresent(stopTime::setStopSequence); stopTime.setPickupType(added.pickup()); stopTime.setDropOffType(added.dropOff()); // Add stop time to list @@ -838,14 +841,14 @@ private Result addTripToGraphAndBuffer( // Update all times to mark trip times as realtime // TODO: This is based on the proposal at https://github.com/google/transit/issues/490 for (int stopIndex = 0; stopIndex < newTripTimes.getNumStops(); stopIndex++) { - final var addedStopTime = AddedStopTime.ofStopTime(stopTimeUpdates.get(stopIndex)); + final var addedStopTime = new AddedStopTime(stopTimeUpdates.get(stopIndex)); - if (addedStopTime.scheduleRelationship == StopTimeUpdate.ScheduleRelationship.SKIPPED) { + if (addedStopTime.isSkipped()) { newTripTimes.setCancelled(stopIndex); } - final int arrivalDelay = Objects.requireNonNullElse(addedStopTime.getArrivalDelay(), 0); - final int departureDelay = Objects.requireNonNullElse(addedStopTime.getDepartureDelay(), 0); + final int arrivalDelay = addedStopTime.getArrivalDelay().orElse(0); + final int departureDelay = addedStopTime.getDepartureDelay().orElse(0); newTripTimes.updateArrivalTime( stopIndex, newTripTimes.getScheduledArrivalTime(stopIndex) + arrivalDelay