
org.opentripplanner.transit.service.StopModel Maven / Gradle / Ivy
package org.opentripplanner.transit.service;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.locationtech.jts.geom.Envelope;
import org.opentripplanner.transit.model.basic.WgsCoordinate;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.site.AreaStop;
import org.opentripplanner.transit.model.site.GroupOfStations;
import org.opentripplanner.transit.model.site.GroupStop;
import org.opentripplanner.transit.model.site.MultiModalStation;
import org.opentripplanner.transit.model.site.RegularStop;
import org.opentripplanner.transit.model.site.Station;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.transit.model.site.StopLocationsGroup;
import org.opentripplanner.util.lang.CollectionsView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Repository for Stop entities.
*/
public class StopModel implements Serializable {
private static final Logger LOG = LoggerFactory.getLogger(StopModel.class);
private final Map regularStopById;
private final Map stationById;
private final Map multiModalStationById;
private final Map groupOfStationsById;
private final Map areaStopById;
private final Map groupStopById;
/** The density center of the graph for determining the initial geographic extent in the client. */
private final WgsCoordinate stopLocationCenter;
private transient StopModelIndex index;
@Inject
public StopModel() {
this.regularStopById = Map.of();
this.stationById = Map.of();
this.multiModalStationById = Map.of();
this.groupOfStationsById = Map.of();
this.areaStopById = Map.of();
this.groupStopById = Map.of();
this.stopLocationCenter = null;
this.index = new StopModelIndex(List.of(), List.of(), List.of(), List.of());
}
public StopModel(StopModelBuilder builder) {
this.regularStopById = builder.regularStopsById().asImmutableMap();
this.stationById = builder.stationById().asImmutableMap();
this.multiModalStationById = builder.multiModalStationById().asImmutableMap();
this.groupOfStationsById = builder.groupOfStationById().asImmutableMap();
this.areaStopById = builder.areaStopById().asImmutableMap();
this.groupStopById = builder.groupStopById().asImmutableMap();
this.stopLocationCenter = builder.calculateTransitCenter();
reindex();
}
public static StopModelBuilder of() {
return new StopModelBuilder();
}
public StopModelBuilder copy() {
return new StopModelBuilder(this);
}
/**
* Return a regular transit stop if found(not flex stops).
*/
public RegularStop getRegularStop(FeedScopedId id) {
return regularStopById.get(id);
}
/**
* Return all regular transit stops, not flex stops and flex group of stops.
*/
public Collection listRegularStops() {
return regularStopById.values();
}
public Collection findRegularStops(Envelope envelope) {
return index.findRegularStops(envelope);
}
public boolean hasAreaStops() {
return !areaStopById.isEmpty();
}
/**
* Flex locations are generated by GTFS graph builder, but consumed only after the street graph is
* built
*/
@Nullable
public AreaStop getAreaStop(FeedScopedId id) {
return areaStopById.get(id);
}
public Collection listAreaStops() {
return areaStopById.values();
}
public Collection queryLocationIndex(Envelope envelope) {
return index.findAreaStops(envelope);
}
public Collection listGroupStops() {
return groupStopById.values();
}
public StopLocation stopByIndex(int stopIndex) {
return index.stopByIndex(stopIndex);
}
public int stopIndexSize() {
return index.stopIndexSize();
}
public Optional stopLocationCenter() {
return Optional.ofNullable(stopLocationCenter);
}
/**
* Return regular transit stop, flex stop or flex group of stops.
*/
@Nullable
public StopLocation getStopLocation(FeedScopedId id) {
return getById(id, regularStopById, areaStopById, groupStopById);
}
/**
* Return all stops including regular transit stops, flex stops and flex group of stops.
*/
public Collection listStopLocations() {
return new CollectionsView<>(
regularStopById.values(),
areaStopById.values(),
groupStopById.values()
);
}
@Nullable
public Station getStationById(FeedScopedId id) {
return stationById.get(id);
}
public Collection listStations() {
return stationById.values();
}
@Nullable
public MultiModalStation getMultiModalStation(FeedScopedId id) {
return multiModalStationById.get(id);
}
public Collection listMultiModalStations() {
return multiModalStationById.values();
}
@Nullable
public MultiModalStation getMultiModalStationForStation(Station station) {
return index.getMultiModalStationForStation(station);
}
public Collection listGroupOfStations() {
return groupOfStationsById.values();
}
/**
* Finds a {@link StopLocationsGroup} by id. Return a station, multimodal station, or group of
* station.
*/
@Nullable
public StopLocationsGroup getStopLocationsGroup(FeedScopedId id) {
return getById(id, stationById, multiModalStationById, groupOfStationsById);
}
/**
* Returns all {@link StopLocationsGroup}s present, including stations, group of stations and
* multimodal stations.
*/
public Collection listStopLocationGroups() {
return new CollectionsView<>(
stationById.values(),
multiModalStationById.values(),
groupOfStationsById.values()
);
}
/**
* @param id Id of Stop, Station, MultiModalStation or GroupOfStations
* @return The coordinate for the transit entity
*/
@Nullable
public WgsCoordinate getCoordinateById(FeedScopedId id) {
// GroupOfStations
GroupOfStations groupOfStations = groupOfStationsById.get(id);
if (groupOfStations != null) {
return groupOfStations.getCoordinate();
}
// Multimodal station
MultiModalStation multiModalStation = multiModalStationById.get(id);
if (multiModalStation != null) {
return multiModalStation.getCoordinate();
}
// Station
Station station = stationById.get(id);
if (station != null) {
return station.getCoordinate();
}
// Single stop (regular transit and flex)
StopLocation stop = getStopLocation(id);
return stop == null ? null : stop.getCoordinate();
}
/**
* Return all stops associated with the given id. If a Station, a MultiModalStation, or a
* GroupOfStations matches the id, then all child stops are returned. If the id matches a regular
* stops, area stop or stop group, then a list with one item is returned.
* An empty list is if nothing is found.
*/
public Collection findStopOrChildStops(FeedScopedId id) {
StopLocationsGroup stops = getStopLocationsGroup(id);
if (stops != null) {
return stops.getChildStops();
}
// Single stop (regular transit and flex)
StopLocation stop = getStopLocation(id);
return stop == null ? List.of() : List.of(stop);
}
/**
* Call this method after deserializing this class. This will reindex the StopModel.
*/
public void reindexAfterDeserialization() {
reindex();
}
private void reindex() {
LOG.info("Index stop model...");
index =
new StopModelIndex(
regularStopById.values(),
areaStopById.values(),
groupStopById.values(),
multiModalStationById.values()
);
LOG.info("Index stop model complete.");
}
@Nullable
@SafeVarargs
private static V getById(FeedScopedId id, Map... maps) {
for (Map map : maps) {
V v = map.get(id);
if (v != null) {
return v;
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy