Search in sources :

Example 1 with StopPlaceRef

use of uk.org.ifopt.siri20.StopPlaceRef 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

Serializable (java.io.Serializable)1 ZonedDateTime (java.time.ZonedDateTime)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 HashSet (java.util.HashSet)1 FeedScopedId (org.opentripplanner.model.FeedScopedId)1 Route (org.opentripplanner.model.Route)1 ServiceDate (org.opentripplanner.model.calendar.ServiceDate)1 EntitySelector (org.opentripplanner.routing.alertpatch.EntitySelector)1 TimePeriod (org.opentripplanner.routing.alertpatch.TimePeriod)1 TransitAlert (org.opentripplanner.routing.alertpatch.TransitAlert)1 I18NString (org.opentripplanner.util.I18NString)1 NonLocalizedString (org.opentripplanner.util.NonLocalizedString)1 TranslatedString (org.opentripplanner.util.TranslatedString)1 StopPlaceRef (uk.org.ifopt.siri20.StopPlaceRef)1