7
7
import org .opentripplanner .routing .algorithm .filterchain .framework .spi .ItineraryDecorator ;
8
8
9
9
/**
10
- * A decorating filter that checks if a transit leg contains any primary stops and if it does,
11
- * then replaces it with the secondary , agency-specific stop name. This is so that the in-vehicle
12
- * display matches what OTP returns as a board/alight stop name.
10
+ * A decorating filter that checks if a transit leg contains any consolidated stops and if it does,
11
+ * then replaces it with the appropriate , agency-specific stop name. This is so that the physical
12
+ * signage and in-vehicle display matches what OTP returns as a board/alight stop name.
13
13
*/
14
14
public class DecorateConsolidatedStopNames implements ItineraryDecorator {
15
15
@@ -21,20 +21,28 @@ public DecorateConsolidatedStopNames(StopConsolidationService service) {
21
21
22
22
@ Override
23
23
public void decorate (Itinerary itinerary ) {
24
- replacePrimaryNamesWithSecondary (itinerary );
24
+ replaceConsolidatedStops (itinerary );
25
25
}
26
26
27
27
/**
28
- * If the itinerary has a from/to that is the primary stop of a {@link org.opentripplanner.ext.stopconsolidation.model.ConsolidatedStopGroup}
29
- * then we replace its name with the secondary name of the agency that is
30
- * operating the route, so that the name in the result matches the name in the in-vehicle
31
- * display.
28
+ * If the itinerary has a "from" stop that is the secondary stop of a
29
+ * {@link org.opentripplanner.ext.stopconsolidation.model.ConsolidatedStopGroup}
30
+ * then we replace its name with the primary name of the agency that is
31
+ * operating the route, so that the name in the result matches the physical signage on the stop.
32
+ * <p>
33
+ * If the leg has a "to" stop that is a primary stop, then we don't want to show the stop that's on
34
+ * the signage but what is shown _inside_ the vehicle. That's why we use the agency-specific (aka
35
+ * secondary) stop.
36
+ * <p>
37
+ * This follows the somewhat idiosyncratic logic of the consolidated stops feature.
32
38
*/
33
- private void replacePrimaryNamesWithSecondary (Itinerary i ) {
39
+ private void replaceConsolidatedStops (Itinerary i ) {
34
40
i .transformTransitLegs (leg -> {
35
41
if (leg instanceof ScheduledTransitLeg stl && needsToRenameStops (stl )) {
36
42
var agency = leg .getAgency ();
43
+ // to show the name on the stop signage we use the primary stop's name
37
44
var from = service .primaryStop (stl .getFrom ().stop .getId ());
45
+ // to show the name that's on the display inside the vehicle we use the agency-specific name
38
46
var to = service .agencySpecificStop (stl .getTo ().stop , agency );
39
47
return new ConsolidatedStopLeg (stl , from , to );
40
48
} else {
@@ -43,6 +51,14 @@ private void replacePrimaryNamesWithSecondary(Itinerary i) {
43
51
});
44
52
}
45
53
54
+ /**
55
+ * Figures out if the from/to stops are part of a consolidated stop group and therefore
56
+ * some stops need to be replaced.
57
+ * <p>
58
+ * Please consult the Javadoc of {@link DecorateConsolidatedStopNames#replaceConsolidatedStops(Itinerary)}
59
+ * for details of this idiosyncratic business logic and in particular why the logic is not the same
60
+ * for the from/to stops.
61
+ */
46
62
private boolean needsToRenameStops (ScheduledTransitLeg stl ) {
47
63
return (service .isSecondaryStop (stl .getFrom ().stop ) || service .isPrimaryStop (stl .getTo ().stop ));
48
64
}
0 commit comments