Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix consolidation stop returning original stop ID. #6156

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ void changeNames() {

var updatedLeg = itinerary.getLegs().getFirst();
assertEquals(STOP_C.getName(), updatedLeg.getFrom().name);
assertEquals(STOP_C.getId(), updatedLeg.getFrom().stop.getId());
assertEquals(STOP_D.getName(), updatedLeg.getTo().name);
assertEquals(STOP_C.getId(), updatedLeg.getTo().stop.getId());

// Check that the fares were carried over
assertEquals(fpu, updatedLeg.fareProducts());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.opentripplanner.ext.stopconsolidation.TestStopConsolidationModel.PATTERN;
import static org.opentripplanner.ext.stopconsolidation.TestStopConsolidationModel.STOP_A;
import static org.opentripplanner.ext.stopconsolidation.TestStopConsolidationModel.STOP_B;
Expand Down Expand Up @@ -29,6 +30,7 @@ void replacePatterns() {
var modifiedPattern = transitModel.getTripPatternForId(PATTERN.getId());
assertFalse(modifiedPattern.getRoutingTripPattern().getPattern().sameAs(PATTERN));
assertFalse(modifiedPattern.sameAs(PATTERN));
assertTrue(modifiedPattern.getScheduledTimetable().getPattern().sameAs(modifiedPattern));

var modifiedStop = modifiedPattern
.getRoutingTripPattern()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public void decorate(Itinerary itinerary) {
* operating the route, so that the name in the result matches the physical signage on the stop.
* <p>
* If the leg has a "to" stop that is a primary stop, then we don't want to show the stop that's on
* the signage but what is shown _inside_ the vehicle. That's why we use the agency-specific (aka
* secondary) stop.
* the signage but what is shown _inside_ the vehicle. However, we still want to use the primary ID
* for stop information and alternatives legs. So we copy the agency-specific (aka secondary) stop
* name to the primary stop object.
* <p>
* This follows the somewhat idiosyncratic logic of the consolidated stops feature.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
import org.opentripplanner.ext.stopconsolidation.StopConsolidationService;
import org.opentripplanner.ext.stopconsolidation.model.ConsolidatedStopGroup;
import org.opentripplanner.ext.stopconsolidation.model.StopReplacement;
import org.opentripplanner.framework.i18n.I18NString;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.organization.Agency;
import org.opentripplanner.transit.model.site.AreaStop;
import org.opentripplanner.transit.model.site.GroupStop;
import org.opentripplanner.transit.model.site.RegularStop;
import org.opentripplanner.transit.model.site.RegularStopBuilder;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.transit.service.TransitModel;
import org.slf4j.Logger;
Expand Down Expand Up @@ -93,7 +98,24 @@ private Optional<StopLocation> findAgencySpecificStop(StopLocation stop, Agency
.flatMap(g -> g.secondaries().stream())
.filter(secondary -> secondary.getFeedId().equals(agency.getId().getFeedId()))
.findAny()
.map(id -> transitModel.getStopModel().getRegularStop(id));
.map(id -> copyStopWithName(stop, transitModel.getStopModel().getRegularStop(id).getName()));
}

private StopLocation copyStopWithName(StopLocation primaryStop, I18NString agencySpecificName) {
if (primaryStop instanceof RegularStop) {
return ((RegularStop) primaryStop).copy().withName(agencySpecificName).build();
}

if (primaryStop instanceof AreaStop) {
return ((AreaStop) primaryStop).copy().withName(agencySpecificName).build();
}

if (primaryStop instanceof GroupStop) {
return ((GroupStop) primaryStop).copy().withName(agencySpecificName).build();
}

// should not happen unless new stop types are added
throw new IllegalArgumentException("Unknown stop location type: " + primaryStop);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;
import org.opentripplanner.framework.time.ServiceDateUtils;
Expand Down Expand Up @@ -483,4 +484,13 @@ private static TripTimes getRepresentativeTripTimes(
return null;
}
}

public boolean sameAs(Timetable other) {
return (
Objects.equals(pattern, other.pattern) &&
Objects.equals(tripTimes, other.tripTimes) &&
Objects.equals(frequencyEntries, other.frequencyEntries) &&
Objects.equals(serviceDate, other.serviceDate)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,7 @@ public final class TripPattern
this.netexSubMode = requireNonNull(builder.getNetexSubmode());
this.containsMultipleModes = builder.getContainsMultipleModes();

if (builder.getScheduledTimetable() != null) {
if (builder.getScheduledTimetableBuilder() != null) {
throw new IllegalArgumentException(
"Cannot provide both scheduled timetable and scheduled timetable builder"
);
}
this.scheduledTimetable = builder.getScheduledTimetable();
} else {
this.scheduledTimetable =
builder.getScheduledTimetableBuilder().withTripPattern(this).build();
}
this.scheduledTimetable = builder.getScheduledTimetableBuilder().withTripPattern(this).build();

this.originalTripPattern = builder.getOriginalTripPattern();

Expand Down Expand Up @@ -469,7 +459,7 @@ public boolean sameAs(TripPattern other) {
Objects.equals(this.containsMultipleModes, other.containsMultipleModes) &&
Objects.equals(this.name, other.name) &&
Objects.equals(this.stopPattern, other.stopPattern) &&
Objects.equals(this.scheduledTimetable, other.scheduledTimetable)
this.scheduledTimetable.sameAs(other.scheduledTimetable)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public final class TripPatternBuilder
private SubMode netexSubMode;
private boolean containsMultipleModes;
private StopPattern stopPattern;
private Timetable scheduledTimetable;
private TimetableBuilder scheduledTimetableBuilder;
private String name;

Expand All @@ -50,7 +49,7 @@ public final class TripPatternBuilder
this.netexSubMode = original.getNetexSubmode();
this.containsMultipleModes = original.getContainsMultipleModes();
this.stopPattern = original.getStopPattern();
this.scheduledTimetable = original.getScheduledTimetable();
this.scheduledTimetableBuilder = original.getScheduledTimetable().copyOf();
this.createdByRealtimeUpdate = original.isCreatedByRealtimeUpdater();
this.originalTripPattern = original.getOriginalTripPattern();
this.hopGeometries =
Expand Down Expand Up @@ -93,24 +92,13 @@ public TripPatternBuilder withStopPattern(StopPattern stopPattern) {
}

public TripPatternBuilder withScheduledTimeTable(Timetable scheduledTimetable) {
if (scheduledTimetableBuilder != null) {
throw new IllegalStateException(
"Cannot set scheduled Timetable after scheduled Timetable builder is created"
);
}
this.scheduledTimetable = scheduledTimetable;
this.scheduledTimetableBuilder = scheduledTimetable.copyOf();
return this;
}

public TripPatternBuilder withScheduledTimeTableBuilder(
UnaryOperator<TimetableBuilder> producer
) {
// create a builder for the scheduled timetable only if it needs to be modified.
// otherwise reuse the existing timetable
if (scheduledTimetableBuilder == null) {
scheduledTimetableBuilder = scheduledTimetable.copyOf();
scheduledTimetable = null;
}
producer.apply(scheduledTimetableBuilder);
return this;
}
Expand Down Expand Up @@ -141,9 +129,6 @@ public int transitReluctanceFactorIndex() {
}

public Direction getDirection() {
if (scheduledTimetable != null) {
return scheduledTimetable.getDirection();
}
return scheduledTimetableBuilder.getDirection();
}

Expand Down Expand Up @@ -172,10 +157,6 @@ public StopPattern getStopPattern() {
return stopPattern;
}

public Timetable getScheduledTimetable() {
return scheduledTimetable;
}

public TimetableBuilder getScheduledTimetableBuilder() {
return scheduledTimetableBuilder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ void copy() {
assertEquals(subject.getHopGeometry(0), copy.getHopGeometry(0));
assertEquals(subject.getHopGeometry(1), copy.getHopGeometry(1));
assertEquals(HOP_GEOMETRIES.get(1), copy.getHopGeometry(1));

// The linked timetable should link back to the new pattern
assertSame(copy, copy.getScheduledTimetable().getPattern());
}

@Test
Expand Down