org.opentripplanner.model.impl.OtpTransitServiceImpl Maven / Gradle / Ivy
/* This file is based on code copied from project OneBusAway, see the LICENSE file for further information. */
package org.opentripplanner.model.impl;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opentripplanner.ext.flex.trip.FlexTrip;
import org.opentripplanner.model.Agency;
import org.opentripplanner.model.BoardingArea;
import org.opentripplanner.model.Entrance;
import org.opentripplanner.model.FareAttribute;
import org.opentripplanner.model.FareRule;
import org.opentripplanner.model.FeedInfo;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.model.FlexLocationGroup;
import org.opentripplanner.model.FlexStopLocation;
import org.opentripplanner.model.GroupOfStations;
import org.opentripplanner.model.MultiModalStation;
import org.opentripplanner.model.Notice;
import org.opentripplanner.model.Operator;
import org.opentripplanner.model.OtpTransitService;
import org.opentripplanner.model.Pathway;
import org.opentripplanner.model.PathwayNode;
import org.opentripplanner.model.ShapePoint;
import org.opentripplanner.model.Station;
import org.opentripplanner.model.Stop;
import org.opentripplanner.model.StopTime;
import org.opentripplanner.model.TransitEntity;
import org.opentripplanner.model.Trip;
import org.opentripplanner.model.TripPattern;
import org.opentripplanner.model.transfer.ConstrainedTransfer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A in-memory implementation of {@link OtpTransitService}. It's super fast for most
* methods, but only if you have enough memory to load your entire {@link OtpTransitService}
* into memory.
*
* This class is read only, to enforce consistency after generating indexes and ids.
* You will get an exception if you try to add entities to one of the collections.
* If you need to modify a {@link OtpTransitService}, you can create a new
* {@link OtpTransitServiceBuilder} based on your old data, do your modification and
* create a new unmodifiable instance.
*/
class OtpTransitServiceImpl implements OtpTransitService {
private static final Logger LOG = LoggerFactory.getLogger(OtpTransitServiceImpl.class);
private final Collection agencies;
private final Collection operators;
private final Collection fareAttributes;
private final Collection fareRules;
private final Collection feedInfos;
private final Collection groupsOfStations;
private final Collection multiModalStations;
private final ImmutableListMultimap noticeAssignments;
private final Collection pathways;
private final Collection serviceIds;
private final Map> shapePointsByShapeId;
private final Map stationsById;
private final Map stopsById;
private final Map entrancesById;
private final Map pathwayNodesById;
private final Map boardingAreasById;
private final Map locationsById;
private final Map locationGroupsById;
private final Map> stopTimesByTrip;
private final Collection transfers;
private final Collection tripPatterns;
private final Collection trips;
private final Collection flexTrips;
/**
* Create a read only version of the {@link OtpTransitService}.
*/
OtpTransitServiceImpl(OtpTransitServiceBuilder builder) {
this.agencies = immutableList(builder.getAgenciesById().values());
this.fareAttributes = immutableList(builder.getFareAttributes());
this.fareRules = immutableList(builder.getFareRules());
this.feedInfos = immutableList(builder.getFeedInfos());
this.groupsOfStations = builder.getGroupsOfStationsById().values();
this.multiModalStations = builder.getMultiModalStationsById().values();
this.noticeAssignments = ImmutableListMultimap.copyOf(builder.getNoticeAssignments());
this.operators = immutableList(builder.getOperatorsById().values());
this.pathways = immutableList(builder.getPathways());
this.serviceIds = immutableList(builder.findAllServiceIds());
this.shapePointsByShapeId = mapShapePoints(builder.getShapePoints());
this.stationsById = builder.getStations().asImmutableMap();
this.stopsById = builder.getStops().asImmutableMap();
this.entrancesById = builder.getEntrances().asImmutableMap();
this.pathwayNodesById = builder.getPathwayNodes().asImmutableMap();
this.boardingAreasById = builder.getBoardingAreas().asImmutableMap();
this.locationsById = builder.getLocations().asImmutableMap();
this.locationGroupsById = builder.getLocationGroups().asImmutableMap();
this.stopTimesByTrip = builder.getStopTimesSortedByTrip().asImmutableMap();
this.transfers = immutableList(builder.getTransfers());
this.tripPatterns = immutableList(builder.getTripPatterns().values());
this.trips = immutableList(builder.getTripsById().values());
this.flexTrips = immutableList(builder.getFlexTripsById().values());
if(!builder.getFrequencies().isEmpty()) {
LOG.error(
"OTP2 do not support GTFS Trip Frequencies. "
+ "See https://github.com/opentripplanner/OpenTripPlanner/issues/3243."
);
}
}
@Override
public Collection getAllAgencies() {
return agencies;
}
@Override
public Collection getAllFareAttributes() {
return fareAttributes;
}
@Override
public Collection getAllFareRules() {
return fareRules;
}
@Override
public Collection getAllFeedInfos() {
return feedInfos;
}
@Override
public Collection getAllGroupsOfStations() {
return immutableList(groupsOfStations);
}
@Override
public Collection getAllMultiModalStations() {
return immutableList(multiModalStations);
}
/**
* Map from Transit Entity(id) to Notices. We need to use Serializable as a common type
* for ids, since some entities have String, while other have FeedScopeId ids.
*/
@Override
public Multimap getNoticeAssignments() {
return noticeAssignments;
}
@Override
public Collection getAllPathways() {
return pathways;
}
@Override
public Collection getAllOperators() {
return operators;
}
@Override
public Collection getAllServiceIds() {
return serviceIds;
}
@Override
public List getShapePointsForShapeId(FeedScopedId shapeId) {
return immutableList(shapePointsByShapeId.get(shapeId));
}
@Override
public Station getStationForId(FeedScopedId id) {
return stationsById.get(id);
}
@Override
public Stop getStopForId(FeedScopedId id) {
return stopsById.get(id);
}
@Override
public Collection getAllStations() {
return immutableList(stationsById.values());
}
@Override
public Collection getAllStops() {
return immutableList(stopsById.values());
}
@Override
public Collection getAllEntrances() {
return immutableList(entrancesById.values());
}
@Override
public Collection getAllPathwayNodes() {
return immutableList(pathwayNodesById.values());
}
@Override
public Collection getAllBoardingAreas() {
return immutableList(boardingAreasById.values());
}
@Override
public Collection getAllLocations() {
return immutableList(locationsById.values());
}
@Override
public Collection getAllLocationGroups() {
return immutableList(locationGroupsById.values());
}
@Override
public List getStopTimesForTrip(Trip trip) {
return immutableList(stopTimesByTrip.get(trip));
}
@Override
public Collection getAllTransfers() {
return transfers;
}
@Override
public Collection getTripPatterns() {
return tripPatterns;
}
@Override
public Collection getAllTrips() {
return trips;
}
@Override
public Collection getAllFlexTrips() {
return flexTrips;
}
/* Private Methods */
private Map> mapShapePoints(
Multimap shapePoints
) {
Map> map = new HashMap<>();
for (Map.Entry> entry
: shapePoints.asMap().entrySet()) {
map.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
for (List list : map.values()) {
Collections.sort(list);
}
return map;
}
/**
* Convert the given collection into a new immutable List.
*/
private static List immutableList(Collection c) {
List list;
if (c instanceof List) {
list = (List) c;
} else {
list = new ArrayList<>(c);
}
return Collections.unmodifiableList(list);
}
}