Skip to content

Commit

Permalink
Prevent modifications on read-only timetables
Browse files Browse the repository at this point in the history
  • Loading branch information
vpaturet committed Jun 28, 2024
1 parent 1850dd1 commit 108f0a2
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 7 deletions.
14 changes: 7 additions & 7 deletions src/main/java/org/opentripplanner/model/TimetableSnapshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public TimetableSnapshot commit(TransitLayerUpdater transitLayerUpdater, boolean
this.dirtyTimetables.clear();
this.dirty = false;

ret.setPatternsForStop(ImmutableSetMultimap.copyOf(patternsForStop));
ret.patternsForStop = ImmutableSetMultimap.copyOf(patternsForStop);

ret.readOnly = true; // mark the snapshot as henceforth immutable
return ret;
Expand Down Expand Up @@ -303,6 +303,10 @@ public void clear(String feedId) {
* message and an attempt was made to re-associate it with its originally scheduled trip pattern.
*/
public boolean revertTripToScheduledTripPattern(FeedScopedId tripId, LocalDate serviceDate) {
if (readOnly) {
throw new ConcurrentModificationException("This TimetableSnapshot is read-only.");
}

boolean success = false;

final TripPattern pattern = getRealtimeAddedTripPattern(tripId, serviceDate);
Expand Down Expand Up @@ -406,10 +410,6 @@ public Collection<TripPattern> getPatternsForStop(StopLocation stop) {
return patternsForStop.get(stop);
}

public void setPatternsForStop(SetMultimap<StopLocation, TripPattern> patternsForStop) {
this.patternsForStop = patternsForStop;
}

/**
* Does this snapshot contain any realtime data or is it completely empty?
*/
Expand All @@ -423,7 +423,7 @@ public boolean isEmpty() {
* @param feedId feed id to clear out
* @return true if the timetable changed as a result of the call
*/
protected boolean clearTimetable(String feedId) {
private boolean clearTimetable(String feedId) {
return timetables.keySet().removeIf(tripPattern -> feedId.equals(tripPattern.getFeedId()));
}

Expand All @@ -433,7 +433,7 @@ protected boolean clearTimetable(String feedId) {
* @param feedId feed id to clear out
* @return true if the realtimeAddedTripPattern changed as a result of the call
*/
protected boolean clearRealtimeAddedTripPattern(String feedId) {
private boolean clearRealtimeAddedTripPattern(String feedId) {
return realtimeAddedTripPattern
.keySet()
.removeIf(realtimeAddedTripPattern ->
Expand Down
47 changes: 47 additions & 0 deletions src/test/java/org/opentripplanner/model/TimetableSnapshotTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.google.transit.realtime.GtfsRealtime.TripDescriptor;
Expand Down Expand Up @@ -261,6 +262,52 @@ public void testPurge() {
assertFalse(resolver.isDirty());
}

@Test
void testCannotUpdateReadOnlyTimetableSnapshot() {
TimetableSnapshot committedSnapshot = createCommittedSnapshot();
LocalDate today = LocalDate.now(timeZone);
TripPattern pattern = patternIndex.get(new FeedScopedId(feedId, "1.1"));
assertThrows(
ConcurrentModificationException.class,
() -> committedSnapshot.update(pattern, null, today)
);
}

@Test
void testCannotCommitReadOnlyTimetableSnapshot() {
TimetableSnapshot committedSnapshot = createCommittedSnapshot();
assertThrows(ConcurrentModificationException.class, () -> committedSnapshot.commit(null, true));
}

@Test
void testCannotClearReadOnlyTimetableSnapshot() {
TimetableSnapshot committedSnapshot = createCommittedSnapshot();
assertThrows(ConcurrentModificationException.class, () -> committedSnapshot.clear(null));
}

@Test
void testCannotPurgeReadOnlyTimetableSnapshot() {
TimetableSnapshot committedSnapshot = createCommittedSnapshot();
assertThrows(
ConcurrentModificationException.class,
() -> committedSnapshot.purgeExpiredData(null)
);
}

@Test
void testCannotRevertReadOnlyTimetableSnapshot() {
TimetableSnapshot committedSnapshot = createCommittedSnapshot();
assertThrows(
ConcurrentModificationException.class,
() -> committedSnapshot.revertTripToScheduledTripPattern(null, null)
);
}

private static TimetableSnapshot createCommittedSnapshot() {
TimetableSnapshot timetableSnapshot = new TimetableSnapshot();
return timetableSnapshot.commit(null, true);
}

private Result<?, UpdateError> updateResolver(
TimetableSnapshot resolver,
TripPattern pattern,
Expand Down

0 comments on commit 108f0a2

Please sign in to comment.