Search in sources :

Example 26 with ServiceDate

use of org.opentripplanner.model.calendar.ServiceDate in project OpenTripPlanner by opentripplanner.

the class SiriTimetableSnapshotSource method handleModifiedTrip.

private boolean handleModifiedTrip(Graph graph, String feedId, EstimatedVehicleJourney estimatedVehicleJourney) {
    // Check if EstimatedVehicleJourney is reported as NOT monitored
    if (estimatedVehicleJourney.isMonitored() != null && !estimatedVehicleJourney.isMonitored()) {
        // Ignore the notMonitored-flag if the journey is NOT monitored because it has been cancelled
        if (estimatedVehicleJourney.isCancellation() != null && !estimatedVehicleJourney.isCancellation()) {
            return false;
        }
    }
    // Values used in logging
    String operatorRef = (estimatedVehicleJourney.getOperatorRef() != null ? estimatedVehicleJourney.getOperatorRef().getValue() : null);
    String vehicleModes = "" + estimatedVehicleJourney.getVehicleModes();
    String lineRef = estimatedVehicleJourney.getLineRef().getValue();
    String vehicleRef = (estimatedVehicleJourney.getVehicleRef() != null ? estimatedVehicleJourney.getVehicleRef().getValue() : null);
    ServiceDate serviceDate = getServiceDateForEstimatedVehicleJourney(estimatedVehicleJourney);
    if (serviceDate == null) {
        return false;
    }
    Set<TripTimes> times = new HashSet<>();
    Set<TripPattern> patterns = new HashSet<>();
    Trip tripMatchedByServiceJourneyId = siriFuzzyTripMatcher.findTripByDatedVehicleJourneyRef(estimatedVehicleJourney);
    if (tripMatchedByServiceJourneyId != null) {
        /*
              Found exact match
             */
        TripPattern exactPattern = routingService.getPatternForTrip().get(tripMatchedByServiceJourneyId);
        if (exactPattern != null) {
            Timetable currentTimetable = getCurrentTimetable(exactPattern, serviceDate);
            TripTimes exactUpdatedTripTimes = createUpdatedTripTimes(graph, currentTimetable, estimatedVehicleJourney, timeZone, tripMatchedByServiceJourneyId.getId());
            if (exactUpdatedTripTimes != null) {
                times.add(exactUpdatedTripTimes);
                patterns.add(exactPattern);
            } else {
                LOG.info("Failed to update TripTimes for trip found by exact match {}", tripMatchedByServiceJourneyId.getId());
                return false;
            }
        }
    } else {
        /*
                No exact match found - search for trips based on arrival-times/stop-patterns
             */
        Set<Trip> trips = siriFuzzyTripMatcher.match(estimatedVehicleJourney);
        if (trips == null || trips.isEmpty()) {
            LOG.debug("No trips found for EstimatedVehicleJourney. [operator={}, vehicleModes={}, lineRef={}, vehicleRef={}]", operatorRef, vehicleModes, lineRef, vehicleRef);
            return false;
        }
        // Find the trips that best corresponds to EstimatedVehicleJourney
        Set<Trip> matchingTrips = getTripForJourney(trips, estimatedVehicleJourney);
        if (matchingTrips == null || matchingTrips.isEmpty()) {
            LOG.debug("Found no matching trip for SIRI ET (serviceDate, departureTime). [operator={}, vehicleModes={}, lineRef={}, vehicleJourneyRef={}]", operatorRef, vehicleModes, lineRef, vehicleRef);
            return false;
        }
        for (Trip matchingTrip : matchingTrips) {
            TripPattern pattern = getPatternForTrip(matchingTrip, estimatedVehicleJourney);
            if (pattern != null) {
                Timetable currentTimetable = getCurrentTimetable(pattern, serviceDate);
                TripTimes updatedTripTimes = createUpdatedTripTimes(graph, currentTimetable, estimatedVehicleJourney, timeZone, matchingTrip.getId());
                if (updatedTripTimes != null) {
                    patterns.add(pattern);
                    times.add(updatedTripTimes);
                }
            }
        }
    }
    if (patterns.isEmpty()) {
        LOG.debug("Found no matching pattern for SIRI ET (firstStopId, lastStopId, numberOfStops). [operator={}, vehicleModes={}, lineRef={}, vehicleRef={}]", operatorRef, vehicleModes, lineRef, vehicleRef);
        return false;
    }
    if (times.isEmpty()) {
        return false;
    }
    boolean result = false;
    for (TripTimes tripTimes : times) {
        Trip trip = tripTimes.trip;
        for (TripPattern pattern : patterns) {
            if (tripTimes.getNumStops() == pattern.stopPattern.stops.length) {
                if (!tripTimes.isCanceled()) {
                    /*
                          UPDATED and MODIFIED tripTimes should be handled the same way to always allow latest realtime-update
                          to replace previous update regardless of realtimestate
                         */
                    cancelScheduledTrip(feedId, trip.getId().getId(), serviceDate);
                    // Check whether trip id has been used for previously ADDED/MODIFIED trip message and cancel
                    // previously created trip
                    cancelPreviouslyAddedTrip(feedId, trip.getId().getId(), serviceDate);
                    // Calculate modified stop-pattern
                    Timetable currentTimetable = getCurrentTimetable(pattern, serviceDate);
                    List<Stop> modifiedStops = createModifiedStops(currentTimetable, estimatedVehicleJourney, routingService);
                    List<StopTime> modifiedStopTimes = createModifiedStopTimes(currentTimetable, tripTimes, estimatedVehicleJourney, trip, routingService);
                    if (modifiedStops != null && modifiedStops.isEmpty()) {
                        tripTimes.cancel();
                    } else {
                        // Add new trip
                        result = result | addTripToGraphAndBuffer(feedId, graph, trip, modifiedStopTimes, modifiedStops, tripTimes, serviceDate);
                    }
                } else {
                    result = result | buffer.update(pattern, tripTimes, serviceDate);
                }
                LOG.debug("Applied realtime data for trip {}", trip.getId().getId());
            } else {
                LOG.debug("Ignoring update since number of stops do not match");
            }
        }
    }
    return result;
}
Also used : Timetable(org.opentripplanner.model.Timetable) Trip(org.opentripplanner.model.Trip) Stop(org.opentripplanner.model.Stop) TripPattern(org.opentripplanner.model.TripPattern) ServiceDate(org.opentripplanner.model.calendar.ServiceDate) TimetableHelper.createUpdatedTripTimes(org.opentripplanner.ext.siri.TimetableHelper.createUpdatedTripTimes) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) HashSet(java.util.HashSet) StopTime(org.opentripplanner.model.StopTime)

Example 27 with ServiceDate

use of org.opentripplanner.model.calendar.ServiceDate in project OpenTripPlanner by opentripplanner.

the class SiriTimetableSnapshotSource method applyVehicleMonitoring.

/**
 * Method to apply a trip update list to the most recent version of the timetable snapshot.
 *
 * @param graph graph to update (needed for adding/changing stop patterns)
 * @param fullDataset true iff the list with updates represent all updates that are active right
 *        now, i.e. all previous updates should be disregarded
 * @param updates SIRI VehicleMonitoringDeliveries that should be applied atomically
 */
public void applyVehicleMonitoring(final Graph graph, final String feedId, final boolean fullDataset, final List<VehicleMonitoringDeliveryStructure> updates) {
    if (updates == null) {
        LOG.warn("updates is null");
        return;
    }
    // Acquire lock on buffer
    bufferLock.lock();
    try {
        if (fullDataset) {
            // Remove all updates from the buffer
            buffer.clear(feedId);
        }
        for (VehicleMonitoringDeliveryStructure vmDelivery : updates) {
            ServiceDate serviceDate = new ServiceDate();
            List<VehicleActivityStructure> activities = vmDelivery.getVehicleActivities();
            if (activities != null) {
                // Handle activities
                LOG.info("Handling {} VM-activities.", activities.size());
                int handledCounter = 0;
                int skippedCounter = 0;
                for (VehicleActivityStructure activity : activities) {
                    boolean handled = handleModifiedTrip(graph, feedId, activity, serviceDate);
                    if (handled) {
                        handledCounter++;
                    } else {
                        skippedCounter++;
                    }
                }
                LOG.info("Applied {} VM-activities, skipped {}.", handledCounter, skippedCounter);
            }
            List<VehicleActivityCancellationStructure> cancellations = vmDelivery.getVehicleActivityCancellations();
            if (cancellations != null && !cancellations.isEmpty()) {
                // Handle cancellations
                LOG.info("TODO: Handle {} cancellations.", cancellations.size());
            }
            List<NaturalLanguageStringStructure> notes = vmDelivery.getVehicleActivityNotes();
            if (notes != null && !notes.isEmpty()) {
                // Handle notes
                LOG.info("TODO: Handle {} notes.", notes.size());
            }
        }
        // Make sure that the public (locking) getTimetableSnapshot function is not called.
        if (purgeExpiredData) {
            final boolean modified = purgeExpiredData();
            getTimetableSnapshot(modified);
        } else {
            getTimetableSnapshot(false);
        }
    } finally {
        // Always release lock
        bufferLock.unlock();
        if (keepLogging) {
            LOG.info("Reducing SIRI-VM logging until restart");
            keepLogging = false;
        }
    }
}
Also used : NaturalLanguageStringStructure(uk.org.siri.siri20.NaturalLanguageStringStructure) VehicleMonitoringDeliveryStructure(uk.org.siri.siri20.VehicleMonitoringDeliveryStructure) ServiceDate(org.opentripplanner.model.calendar.ServiceDate) VehicleActivityStructure(uk.org.siri.siri20.VehicleActivityStructure) VehicleActivityCancellationStructure(uk.org.siri.siri20.VehicleActivityCancellationStructure)

Example 28 with ServiceDate

use of org.opentripplanner.model.calendar.ServiceDate in project OpenTripPlanner by opentripplanner.

the class SiriTimetableSnapshotSource method purgeExpiredData.

private boolean purgeExpiredData() {
    final ServiceDate today = new ServiceDate();
    // Just to be safe...
    final ServiceDate previously = today.previous().previous();
    if (lastPurgeDate != null && lastPurgeDate.compareTo(previously) > 0) {
        return false;
    }
    LOG.debug("purging expired realtime data");
    lastPurgeDate = previously;
    return buffer.purgeExpiredData(previously);
}
Also used : ServiceDate(org.opentripplanner.model.calendar.ServiceDate)

Example 29 with ServiceDate

use of org.opentripplanner.model.calendar.ServiceDate in project OpenTripPlanner by opentripplanner.

the class SiriTimetableSnapshotSource method getPatternForTrip.

private TripPattern getPatternForTrip(Trip trip, EstimatedVehicleJourney journey) {
    Set<ServiceDate> serviceDates = routingService.getCalendarService().getServiceDatesForServiceId(trip.getServiceId());
    List<RecordedCall> recordedCalls = (journey.getRecordedCalls() != null ? journey.getRecordedCalls().getRecordedCalls() : new ArrayList<>());
    List<EstimatedCall> estimatedCalls = journey.getEstimatedCalls().getEstimatedCalls();
    String journeyFirstStopId;
    ServiceDate journeyDate;
    if (recordedCalls != null && !recordedCalls.isEmpty()) {
        RecordedCall recordedCall = recordedCalls.get(0);
        journeyFirstStopId = recordedCall.getStopPointRef().getValue();
        journeyDate = new ServiceDate(Date.from(recordedCall.getAimedDepartureTime().toInstant()));
    } else if (estimatedCalls != null && !estimatedCalls.isEmpty()) {
        EstimatedCall estimatedCall = estimatedCalls.get(0);
        journeyFirstStopId = estimatedCall.getStopPointRef().getValue();
        journeyDate = new ServiceDate(Date.from(estimatedCall.getAimedDepartureTime().toInstant()));
    } else {
        return null;
    }
    String journeyLastStopId = estimatedCalls.get(estimatedCalls.size() - 1).getStopPointRef().getValue();
    TripPattern lastAddedTripPattern = null;
    if (getTimetableSnapshot() != null) {
        lastAddedTripPattern = getTimetableSnapshot().getLastAddedTripPattern(trip.getId(), journeyDate);
    }
    TripPattern tripPattern;
    if (lastAddedTripPattern != null) {
        tripPattern = lastAddedTripPattern;
    } else {
        tripPattern = routingService.getPatternForTrip().get(trip);
    }
    Stop firstStop = tripPattern.getStop(0);
    Stop lastStop = tripPattern.getStop(tripPattern.getStops().size() - 1);
    if (serviceDates.contains(journeyDate)) {
        boolean firstStopIsMatch = firstStop.getId().getId().equals(journeyFirstStopId);
        boolean lastStopIsMatch = lastStop.getId().getId().equals(journeyLastStopId);
        if (!firstStopIsMatch && firstStop.isPartOfStation()) {
            Stop otherFirstStop = routingService.getStopForId(new FeedScopedId(firstStop.getId().getFeedId(), journeyFirstStopId));
            firstStopIsMatch = firstStop.isPartOfSameStationAs(otherFirstStop);
        }
        if (!lastStopIsMatch && lastStop.isPartOfStation()) {
            Stop otherLastStop = routingService.getStopForId(new FeedScopedId(lastStop.getId().getFeedId(), journeyLastStopId));
            lastStopIsMatch = lastStop.isPartOfSameStationAs(otherLastStop);
        }
        if (firstStopIsMatch & lastStopIsMatch) {
            // Found matches
            return tripPattern;
        }
        return null;
    }
    return null;
}
Also used : ServiceDate(org.opentripplanner.model.calendar.ServiceDate) Stop(org.opentripplanner.model.Stop) ArrayList(java.util.ArrayList) FeedScopedId(org.opentripplanner.model.FeedScopedId) RecordedCall(uk.org.siri.siri20.RecordedCall) EstimatedCall(uk.org.siri.siri20.EstimatedCall) TripPattern(org.opentripplanner.model.TripPattern)

Example 30 with ServiceDate

use of org.opentripplanner.model.calendar.ServiceDate in project OpenTripPlanner by opentripplanner.

the class SiriAlertsUpdateHandler method handleAlert.

private TransitAlert handleAlert(PtSituationElement situation) {
    TransitAlert alert = createAlertWithTexts(situation);
    // If situation is closed, it must be allowed - it will remove already existing alerts
    if ((alert.alertHeaderText == null || alert.alertHeaderText.toString().isEmpty()) && (alert.alertDescriptionText == null || alert.alertDescriptionText.toString().isEmpty()) && (alert.alertDetailText == null || alert.alertDetailText.toString().isEmpty())) {
        LOG.debug("Empty Alert - ignoring situationNumber: {}", situation.getSituationNumber() != null ? situation.getSituationNumber().getValue() : null);
        return null;
    }
    ArrayList<TimePeriod> periods = new ArrayList<>();
    if (situation.getValidityPeriods().size() > 0) {
        for (HalfOpenTimestampOutputRangeStructure activePeriod : situation.getValidityPeriods()) {
            final long realStart = activePeriod.getStartTime() != null ? activePeriod.getStartTime().toInstant().toEpochMilli() : 0;
            final long start = activePeriod.getStartTime() != null ? realStart - earlyStart : 0;
            final long realEnd = activePeriod.getEndTime() != null ? activePeriod.getEndTime().toInstant().toEpochMilli() : 0;
            final long end = activePeriod.getEndTime() != null ? realEnd : 0;
            periods.add(new TimePeriod(start / 1000, end / 1000));
        }
    } else {
        // Per the GTFS-rt spec, if an alert has no TimeRanges, than it should always be shown.
        periods.add(new TimePeriod(0, Long.MAX_VALUE));
    }
    alert.setTimePeriods(periods);
    AffectsScopeStructure affectsStructure = situation.getAffects();
    if (affectsStructure != null) {
        AffectsScopeStructure.Operators operators = affectsStructure.getOperators();
        if (operators != null && !isListNullOrEmpty(operators.getAffectedOperators())) {
            for (AffectedOperatorStructure affectedOperator : operators.getAffectedOperators()) {
                OperatorRefStructure operatorRef = affectedOperator.getOperatorRef();
                if (operatorRef == null || operatorRef.getValue() == null) {
                    continue;
                }
                // SIRI Operators are mapped to OTP Agency, this i probably wrong - but
                // I leave this for now.
                String agencyId = operatorRef.getValue();
                alert.addEntity(new EntitySelector.Agency(new FeedScopedId(feedId, agencyId)));
            }
        }
        AffectsScopeStructure.Networks networks = affectsStructure.getNetworks();
        Set<Route> stopRoutes = new HashSet<>();
        if (networks != null) {
            for (AffectsScopeStructure.Networks.AffectedNetwork affectedNetwork : networks.getAffectedNetworks()) {
                List<AffectedLineStructure> affectedLines = affectedNetwork.getAffectedLines();
                if (affectedLines != null && !isListNullOrEmpty(affectedLines)) {
                    for (AffectedLineStructure line : affectedLines) {
                        LineRef lineRef = line.getLineRef();
                        if (lineRef == null || lineRef.getValue() == null) {
                            continue;
                        }
                        stopRoutes.addAll(siriFuzzyTripMatcher.getRoutes(lineRef.getValue()));
                    }
                }
            }
        }
        AffectsScopeStructure.StopPoints stopPoints = affectsStructure.getStopPoints();
        AffectsScopeStructure.StopPlaces stopPlaces = affectsStructure.getStopPlaces();
        if (stopPoints != null && !isListNullOrEmpty(stopPoints.getAffectedStopPoints())) {
            for (AffectedStopPointStructure stopPoint : stopPoints.getAffectedStopPoints()) {
                StopPointRef stopPointRef = stopPoint.getStopPointRef();
                if (stopPointRef == null || stopPointRef.getValue() == null) {
                    continue;
                }
                FeedScopedId stopId = siriFuzzyTripMatcher.getStop(stopPointRef.getValue());
                if (stopId != null) {
                    if (stopRoutes.isEmpty()) {
                        alert.addEntity(new EntitySelector.Stop(stopId));
                        // TODO: is this correct? Should the stop conditions be in the entity selector?
                        updateStopConditions(alert, stopPoint.getStopConditions());
                    } else {
                        // Adding combination of stop & route
                        for (Route route : stopRoutes) {
                            alert.addEntity(new EntitySelector.StopAndRoute(stopId, route.getId()));
                            // TODO: is this correct? Should the stop conditions be in the entity selector?
                            updateStopConditions(alert, stopPoint.getStopConditions());
                        }
                    }
                }
            }
        } else if (stopPlaces != null && !isListNullOrEmpty(stopPlaces.getAffectedStopPlaces())) {
            for (AffectedStopPlaceStructure stopPoint : stopPlaces.getAffectedStopPlaces()) {
                StopPlaceRef stopPlace = stopPoint.getStopPlaceRef();
                if (stopPlace == null || stopPlace.getValue() == null) {
                    continue;
                }
                FeedScopedId stopId = siriFuzzyTripMatcher.getStop(stopPlace.getValue());
                if (stopId != null) {
                    if (stopRoutes.isEmpty()) {
                        alert.addEntity(new EntitySelector.Stop(stopId));
                    } else {
                        // Adding combination of stop & route
                        for (Route route : stopRoutes) {
                            alert.addEntity(new EntitySelector.StopAndRoute(stopId, route.getId()));
                        }
                    }
                }
            }
        } else if (networks != null && !isListNullOrEmpty(networks.getAffectedNetworks())) {
            for (AffectsScopeStructure.Networks.AffectedNetwork affectedNetwork : networks.getAffectedNetworks()) {
                List<AffectedLineStructure> affectedLines = affectedNetwork.getAffectedLines();
                if (affectedLines != null && !isListNullOrEmpty(affectedLines)) {
                    for (AffectedLineStructure line : affectedLines) {
                        LineRef lineRef = line.getLineRef();
                        if (lineRef == null || lineRef.getValue() == null) {
                            continue;
                        }
                        List<AffectedStopPointStructure> affectedStops = new ArrayList<>();
                        AffectedLineStructure.Routes routes = line.getRoutes();
                        // Resolve AffectedStop-ids
                        if (routes != null) {
                            for (AffectedRouteStructure route : routes.getAffectedRoutes()) {
                                if (route.getStopPoints() != null) {
                                    List<Serializable> stopPointsList = route.getStopPoints().getAffectedStopPointsAndLinkProjectionToNextStopPoints();
                                    for (Serializable serializable : stopPointsList) {
                                        if (serializable instanceof AffectedStopPointStructure) {
                                            AffectedStopPointStructure stopPointStructure = (AffectedStopPointStructure) serializable;
                                            affectedStops.add(stopPointStructure);
                                        }
                                    }
                                }
                            }
                        }
                        Set<Route> affectedRoutes = siriFuzzyTripMatcher.getRoutes(lineRef.getValue());
                        for (Route route : affectedRoutes) {
                            if (!affectedStops.isEmpty()) {
                                for (AffectedStopPointStructure affectedStop : affectedStops) {
                                    FeedScopedId stop = siriFuzzyTripMatcher.getStop(affectedStop.getStopPointRef().getValue());
                                    if (stop == null) {
                                        continue;
                                    }
                                    alert.addEntity(new EntitySelector.StopAndRoute(stop, route.getId()));
                                    // TODO: is this correct? Should the stop conditions be in the entity selector?
                                    updateStopConditions(alert, affectedStop.getStopConditions());
                                }
                            } else {
                                alert.addEntity(new EntitySelector.Route(route.getId()));
                            }
                        }
                    }
                } else {
                    NetworkRefStructure networkRef = affectedNetwork.getNetworkRef();
                    if (networkRef == null || networkRef.getValue() == null) {
                        continue;
                    }
                    String networkId = networkRef.getValue();
                // TODO: What to do here?
                }
            }
        }
        AffectsScopeStructure.VehicleJourneys vjs = affectsStructure.getVehicleJourneys();
        if (vjs != null && !isListNullOrEmpty(vjs.getAffectedVehicleJourneies())) {
            for (AffectedVehicleJourneyStructure affectedVehicleJourney : vjs.getAffectedVehicleJourneies()) {
                String lineRef = null;
                if (affectedVehicleJourney.getLineRef() != null) {
                    lineRef = affectedVehicleJourney.getLineRef().getValue();
                }
                List<AffectedStopPointStructure> affectedStops = new ArrayList<>();
                List<AffectedRouteStructure> routes = affectedVehicleJourney.getRoutes();
                // Resolve AffectedStop-ids
                if (routes != null) {
                    for (AffectedRouteStructure route : routes) {
                        if (route.getStopPoints() != null) {
                            List<Serializable> stopPointsList = route.getStopPoints().getAffectedStopPointsAndLinkProjectionToNextStopPoints();
                            for (Serializable serializable : stopPointsList) {
                                if (serializable instanceof AffectedStopPointStructure) {
                                    AffectedStopPointStructure stopPointStructure = (AffectedStopPointStructure) serializable;
                                    affectedStops.add(stopPointStructure);
                                }
                            }
                        }
                    }
                }
                List<VehicleJourneyRef> vehicleJourneyReves = affectedVehicleJourney.getVehicleJourneyReves();
                if (!isListNullOrEmpty(vehicleJourneyReves)) {
                    for (VehicleJourneyRef vehicleJourneyRef : vehicleJourneyReves) {
                        List<FeedScopedId> tripIds = new ArrayList<>();
                        FeedScopedId tripIdFromVehicleJourney = siriFuzzyTripMatcher.getTripId(vehicleJourneyRef.getValue());
                        Date effectiveStartDate;
                        Date effectiveEndDate;
                        // Need to know if validity is set explicitly or calculated based on ServiceDate
                        boolean effectiveValiditySetExplicitly = false;
                        ZonedDateTime originAimedDepartureTime = (affectedVehicleJourney.getOriginAimedDepartureTime() != null ? affectedVehicleJourney.getOriginAimedDepartureTime() : ZonedDateTime.now());
                        ServiceDate serviceDate = new ServiceDate(originAimedDepartureTime.getYear(), originAimedDepartureTime.getMonthValue(), originAimedDepartureTime.getDayOfMonth());
                        if (tripIdFromVehicleJourney != null) {
                            tripIds.add(tripIdFromVehicleJourney);
                            // ServiceJourneyId matches - use provided validity
                            effectiveStartDate = alert.getEffectiveStartDate();
                            effectiveEndDate = alert.getEffectiveEndDate();
                            effectiveValiditySetExplicitly = true;
                        } else {
                            // TODO - SIRI: Support submode when fuzzy-searching for trips
                            tripIds = siriFuzzyTripMatcher.getTripIdForTripShortNameServiceDateAndMode(vehicleJourneyRef.getValue(), serviceDate, TraverseMode.RAIL);
                            // ServiceJourneyId does NOT match - calculate validity based on originAimedDepartureTime
                            effectiveStartDate = serviceDate.getAsDate();
                            effectiveEndDate = serviceDate.next().getAsDate();
                        }
                        for (FeedScopedId tripId : tripIds) {
                            if (!effectiveValiditySetExplicitly) {
                                // Effective validity is set based on ServiceDate - need to calculate correct validity based on departuretimes
                                // Calculate validity based on actual, planned departure/arrival for trip
                                int tripDepartureTime = siriFuzzyTripMatcher.getTripDepartureTime(tripId);
                                int tripArrivalTime = siriFuzzyTripMatcher.getTripArrivalTime(tripId);
                                // ServiceJourneyId does NOT match - calculate validity based on serviceDate (calculated from originalAimedDepartureTime)
                                effectiveStartDate = new Date(serviceDate.getAsDate().getTime() + tripDepartureTime * 1000);
                                // Appending 6 hours to end-validity in case of delays.
                                effectiveEndDate = new Date(effectiveStartDate.getTime() + (tripArrivalTime - tripDepartureTime + 6 * 3600) * 1000);
                                // Verify that calculated validity does not exceed explicitly set validity
                                if (effectiveStartDate.before(alert.getEffectiveStartDate())) {
                                    effectiveStartDate = alert.getEffectiveStartDate();
                                }
                                if (effectiveEndDate.after(alert.getEffectiveEndDate())) {
                                    effectiveEndDate = alert.getEffectiveEndDate();
                                }
                                if (effectiveStartDate.after(effectiveEndDate) | effectiveStartDate.equals(effectiveEndDate)) {
                                    // Ignore this as situation is no longer valid
                                    continue;
                                }
                            }
                            if (effectiveEndDate == null) {
                                effectiveEndDate = new Date(Long.MAX_VALUE);
                            }
                            if (!affectedStops.isEmpty()) {
                                for (AffectedStopPointStructure affectedStop : affectedStops) {
                                    FeedScopedId stop = siriFuzzyTripMatcher.getStop(affectedStop.getStopPointRef().getValue());
                                    if (stop == null) {
                                        continue;
                                    }
                                    // Creating unique, deterministic id for the alert
                                    alert.addEntity(new EntitySelector.StopAndTrip(stop, tripId));
                                    // TODO: is this correct? Should the stop conditions be in the entity selector?
                                    updateStopConditions(alert, affectedStop.getStopConditions());
                                    // A tripId for a given date may be reused for other dates not affected by this alert.
                                    List<TimePeriod> timePeriodList = new ArrayList<>();
                                    timePeriodList.add(new TimePeriod(effectiveStartDate.getTime() / 1000, effectiveEndDate.getTime() / 1000));
                                // TODO: Make it possible to add time periods for trip selectors
                                // alert.setTimePeriods(timePeriodList);
                                }
                            } else {
                                alert.addEntity(new EntitySelector.Trip(tripId));
                                // A tripId for a given date may be reused for other dates not affected by this alert.
                                List<TimePeriod> timePeriodList = new ArrayList<>();
                                timePeriodList.add(new TimePeriod(effectiveStartDate.getTime() / 1000, effectiveEndDate.getTime() / 1000));
                            // TODO: Make it possible to add time periods for trip selectors
                            // alert.setTimePeriods(timePeriodList);
                            }
                        }
                    }
                }
                if (lineRef != null) {
                    Set<Route> affectedRoutes = siriFuzzyTripMatcher.getRoutes(lineRef);
                    for (Route route : affectedRoutes) {
                        alert.addEntity(new EntitySelector.Route(route.getId()));
                    }
                }
            }
        }
    }
    if (alert.getStopConditions().isEmpty()) {
        updateStopConditions(alert, null);
    }
    alert.alertType = situation.getReportType();
    if (situation.getSeverity() != null) {
        alert.severity = situation.getSeverity().value();
    } else {
        // When severity is not set - use default
        alert.severity = SeverityEnumeration.NORMAL.value();
    }
    if (situation.getParticipantRef() != null) {
        String codespace = situation.getParticipantRef().getValue();
        // TODO - SIRI: Should probably not assume this codespace -> authority rule
        alert.setFeedId(codespace + ":Authority:" + codespace);
    }
    return alert;
}
Also used : Serializable(java.io.Serializable) ArrayList(java.util.ArrayList) NonLocalizedString(org.opentripplanner.util.NonLocalizedString) TranslatedString(org.opentripplanner.util.TranslatedString) I18NString(org.opentripplanner.util.I18NString) ServiceDate(org.opentripplanner.model.calendar.ServiceDate) ZonedDateTime(java.time.ZonedDateTime) Route(org.opentripplanner.model.Route) HashSet(java.util.HashSet) TimePeriod(org.opentripplanner.routing.alertpatch.TimePeriod) TransitAlert(org.opentripplanner.routing.alertpatch.TransitAlert) EntitySelector(org.opentripplanner.routing.alertpatch.EntitySelector) StopPlaceRef(uk.org.ifopt.siri20.StopPlaceRef) Date(java.util.Date) ServiceDate(org.opentripplanner.model.calendar.ServiceDate) FeedScopedId(org.opentripplanner.model.FeedScopedId)

Aggregations

ServiceDate (org.opentripplanner.model.calendar.ServiceDate)40 FeedScopedId (org.opentripplanner.model.FeedScopedId)15 ArrayList (java.util.ArrayList)11 TripPattern (org.opentripplanner.model.TripPattern)10 Test (org.junit.Test)9 Stop (org.opentripplanner.model.Stop)9 Trip (org.opentripplanner.model.Trip)9 TripUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate)8 Date (java.util.Date)8 HashSet (java.util.HashSet)7 TripDescriptor (com.google.transit.realtime.GtfsRealtime.TripDescriptor)6 ZonedDateTime (java.time.ZonedDateTime)6 TripTimeShort (org.opentripplanner.model.TripTimeShort)6 TripTimes (org.opentripplanner.routing.trippattern.TripTimes)6 Calendar (java.util.Calendar)5 Timetable (org.opentripplanner.model.Timetable)4 ServiceCalendarDate (org.opentripplanner.model.calendar.ServiceCalendarDate)4 EstimatedCall (uk.org.siri.siri20.EstimatedCall)4 TimetableHelper.createUpdatedTripTimes (org.opentripplanner.ext.siri.TimetableHelper.createUpdatedTripTimes)3 Route (org.opentripplanner.model.Route)3