From e7e38e409cf2501b00a2876e988ae383bf827810 Mon Sep 17 00:00:00 2001 From: Vincent Paturet Date: Fri, 24 May 2024 14:12:50 +0200 Subject: [PATCH] Add validation for scheduled data in SIRI update --- .../siri/SiriTimetableSnapshotSourceTest.java | 25 +++++++++++++++++++ .../ext/siri/AddedTripBuilder.java | 5 ++++ .../model/timetable/RealTimeTripTimes.java | 4 ++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java b/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java index fa1af949bd3..c3919562af4 100644 --- a/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java @@ -79,6 +79,31 @@ void testAddJourney() { assertEquals(4 * 60, tripTimes.getDepartureTime(1)); } + @Test + void testAddedJourneyWithInvalidScheduledData() { + var env = new RealtimeTestEnvironment(); + + // Create an extra journey with invalid planned data (travel back in time) + // and valid real time data + var createExtraJourney = new SiriEtBuilder(env.getDateTimeHelper()) + .withEstimatedVehicleJourneyCode("newJourney") + .withIsExtraJourney(true) + .withOperatorRef(env.operator1Id.getId()) + .withLineRef(env.route1Id.getId()) + .withEstimatedCalls(builder -> + builder + .call(env.stopA1) + .departAimedExpected("10:58", "10:48") + .call(env.stopB1) + .arriveAimedExpected("10:08", "10:58") + ) + .buildEstimatedTimetableDeliveries(); + + var result = env.applyEstimatedTimetable(createExtraJourney); + assertEquals(0, result.successful()); + assertFailure(result, UpdateError.UpdateErrorType.NEGATIVE_HOP_TIME); + } + @Test void testReplaceJourney() { var env = new RealtimeTestEnvironment(); diff --git a/src/ext/java/org/opentripplanner/ext/siri/AddedTripBuilder.java b/src/ext/java/org/opentripplanner/ext/siri/AddedTripBuilder.java index 7f0e51fab18..8eae3be7077 100644 --- a/src/ext/java/org/opentripplanner/ext/siri/AddedTripBuilder.java +++ b/src/ext/java/org/opentripplanner/ext/siri/AddedTripBuilder.java @@ -216,6 +216,11 @@ Result build() { aimedStopTimes, transitModel.getDeduplicator() ); + // validate the scheduled trip times + // they are in general superseded by real-time trip times + // but in case of trip cancellation, OTP will fall back to scheduled trip times + // therefore they must be valid + tripTimes.validateNonIncreasingTimes(); tripTimes.setServiceCode(transitModel.getServiceCodes().get(trip.getServiceId())); pattern.add(tripTimes); RealTimeTripTimes updatedTripTimes = tripTimes.copyScheduledTimes(); diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java index a62da95e79a..9e91d691fbe 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java @@ -263,7 +263,9 @@ public void setRealTimeState(final RealTimeState realTimeState) { * found. */ public void validateNonIncreasingTimes() { - final int nStops = arrivalTimes.length; + final int nStops = arrivalTimes != null + ? arrivalTimes.length + : scheduledTripTimes.getNumStops(); int prevDep = -9_999_999; for (int s = 0; s < nStops; s++) { final int arr = getArrivalTime(s);