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;
}
Aggregations