org.opentripplanner.netex.loader.mapping.StopTimesMapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.netex.loader.mapping;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.model.Stop;
import org.opentripplanner.model.StopTime;
import org.opentripplanner.model.Trip;
import org.opentripplanner.model.impl.EntityById;
import org.opentripplanner.netex.loader.util.ReadOnlyHierarchicalMap;
import org.rutebanken.netex.model.DestinationDisplay;
import org.rutebanken.netex.model.JourneyPattern;
import org.rutebanken.netex.model.PointInLinkSequence_VersionedChildStructure;
import org.rutebanken.netex.model.StopPointInJourneyPattern;
import org.rutebanken.netex.model.TimetabledPassingTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.opentripplanner.model.StopPattern.PICKDROP_COORDINATE_WITH_DRIVER;
import static org.opentripplanner.model.StopPattern.PICKDROP_NONE;
import static org.opentripplanner.model.StopPattern.PICKDROP_SCHEDULED;
/**
* This maps a list of TimetabledPassingTimes to a list of StopTimes. It also makes sure the StopTime has a reference
* to the correct stop. DestinationDisplay is mapped to HeadSign. There is logic to take care of the the fact that
* DestinationsDisplay is also valid for each subsequent TimeTabledPassingTime, while HeadSign has to be explicitly
* defined for each StopTime.
*/
class StopTimesMapper {
private static final Logger LOG = LoggerFactory.getLogger(TripPatternMapper.class);
private static final int DAY_IN_SECONDS = 3600 * 24;
private final FeedScopedIdFactory idFactory;
private final ReadOnlyHierarchicalMap destinationDisplayById;
private final EntityById stopsById;
private final ReadOnlyHierarchicalMap quayIdByStopPointRef;
private String currentHeadSign;
StopTimesMapper(
FeedScopedIdFactory idFactory,
EntityById stopsById,
ReadOnlyHierarchicalMap destinationDisplayById,
ReadOnlyHierarchicalMap quayIdByStopPointRef
) {
this.idFactory = idFactory;
this.destinationDisplayById = destinationDisplayById;
this.stopsById = stopsById;
this.quayIdByStopPointRef = quayIdByStopPointRef;
}
/**
* @return a map of stop-times indexed by the TimetabledPassingTime id.
*/
MappedStopTimes mapToStopTimes(
JourneyPattern journeyPattern,
Trip trip,
List passingTimes
) {
MappedStopTimes result = new MappedStopTimes();
for (int i = 0; i < passingTimes.size(); i++) {
TimetabledPassingTime currentPassingTime = passingTimes.get(i);
String pointInJourneyPattern = currentPassingTime.getPointInJourneyPatternRef().getValue().getRef();
StopPointInJourneyPattern stopPoint = findStopPoint(pointInJourneyPattern, journeyPattern);
Stop stop = lookupStop(stopPoint, quayIdByStopPointRef, stopsById);
if (stop == null) {
LOG.warn("Stop with id {} not found for StopPoint {} in JourneyPattern {}. "
+ "Trip {} will not be mapped.",
stopPoint != null && stopPoint.getScheduledStopPointRef() != null
? stopPoint.getScheduledStopPointRef().getValue().getRef()
: "null"
, stopPoint != null ? stopPoint.getId() : "null"
, journeyPattern.getId()
, trip.getId());
return null;
}
StopTime stopTime = mapToStopTime(trip, stopPoint, stop, currentPassingTime, i);
result.add(currentPassingTime.getId(), stopTime);
}
return result;
}
static class MappedStopTimes {
Map stopTimeByNetexId = new HashMap<>();
List stopTimes = new ArrayList<>();
void add(String netexId, StopTime stopTime) {
stopTimeByNetexId.put(netexId, stopTime);
stopTimes.add(stopTime);
}
}
private StopTime mapToStopTime(
Trip trip,
StopPointInJourneyPattern stopPoint,
Stop stop,
TimetabledPassingTime passingTime,
int stopSequence
) {
StopTime stopTime = new StopTime();
stopTime.setTrip(trip);
stopTime.setStopSequence(stopSequence);
stopTime.setStop(stop);
stopTime.setArrivalTime(
calculateOtpTime(passingTime.getArrivalTime(), passingTime.getArrivalDayOffset(),
passingTime.getDepartureTime(), passingTime.getDepartureDayOffset()));
stopTime.setDepartureTime(calculateOtpTime(passingTime.getDepartureTime(),
passingTime.getDepartureDayOffset(), passingTime.getArrivalTime(),
passingTime.getArrivalDayOffset()));
if (stopPoint != null) {
if (isFalse(stopPoint.isForAlighting())) {
stopTime.setDropOffType(PICKDROP_NONE);
} else if (Boolean.TRUE.equals(stopPoint.isRequestStop())) {
stopTime.setDropOffType(PICKDROP_COORDINATE_WITH_DRIVER);
} else {
stopTime.setDropOffType(PICKDROP_SCHEDULED);
}
if (isFalse(stopPoint.isForBoarding())) {
stopTime.setPickupType(PICKDROP_NONE);
} else if (Boolean.TRUE.equals(stopPoint.isRequestStop())) {
stopTime.setPickupType(PICKDROP_COORDINATE_WITH_DRIVER);
} else {
stopTime.setPickupType(PICKDROP_SCHEDULED);
}
if (stopPoint.getDestinationDisplayRef() != null) {
DestinationDisplay destinationDisplay =
destinationDisplayById.lookup(stopPoint.getDestinationDisplayRef().getRef());
if (destinationDisplay != null) {
currentHeadSign = destinationDisplay.getFrontText().getValue();
}
}
}
if (passingTime.getArrivalTime() == null && passingTime.getDepartureTime() == null) {
LOG.warn("Time missing for trip " + trip.getId());
}
if (currentHeadSign != null) {
stopTime.setStopHeadsign(currentHeadSign);
}
return stopTime;
}
private Stop lookupStop(
StopPointInJourneyPattern stopPointInJourneyPattern,
ReadOnlyHierarchicalMap quayIdByStopPointRef,
EntityById stopsById
) {
if (stopPointInJourneyPattern == null) return null;
String stopPointRef = stopPointInJourneyPattern.getScheduledStopPointRef().getValue().getRef();
String stopId = quayIdByStopPointRef.lookup(stopPointRef);
if (stopId == null) {
LOG.warn("No passengerStopAssignment found for " + stopPointRef);
return null;
}
Stop stop = stopsById.get(idFactory.createId(stopId));
if (stop == null) {
LOG.warn("Quay not found for " + stopPointRef);
}
return stop;
}
private static StopPointInJourneyPattern findStopPoint(String pointInJourneyPatterRef,
JourneyPattern journeyPattern) {
List points = journeyPattern
.getPointsInSequence()
.getPointInJourneyPatternOrStopPointInJourneyPatternOrTimingPointInJourneyPattern();
for (PointInLinkSequence_VersionedChildStructure point : points) {
if (point instanceof StopPointInJourneyPattern) {
StopPointInJourneyPattern stopPoint = (StopPointInJourneyPattern) point;
if (stopPoint.getId().equals(pointInJourneyPatterRef)) {
return stopPoint;
}
}
}
return null;
}
private static int calculateOtpTime(LocalTime time, BigInteger dayOffset,
LocalTime fallbackTime, BigInteger fallbackDayOffset) {
return time != null ?
calculateOtpTime(time, dayOffset) :
calculateOtpTime(fallbackTime, fallbackDayOffset);
}
static int calculateOtpTime(LocalTime time, BigInteger dayOffset) {
int otpTime = time.toSecondOfDay();
if (dayOffset != null) {
otpTime += DAY_IN_SECONDS * dayOffset.intValue();
}
return otpTime;
}
private static boolean isFalse(Boolean value) {
return value != null && !value;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy