org.onebusaway.gtfs.impl.GtfsRelationalDaoImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of onebusaway-gtfs Show documentation
Show all versions of onebusaway-gtfs Show documentation
A Java library for reading and writing General Transit Feed Spec feeds
/**
* Copyright (C) 2011 Brian Ferris
* Copyright (C) 2011 Google, Inc.
* Copyright (C) 2011 Laurent Gregoire
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.gtfs.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.onebusaway.csv_entities.exceptions.EntityInstantiationException;
import org.onebusaway.csv_entities.schema.BeanWrapper;
import org.onebusaway.csv_entities.schema.BeanWrapperFactory;
import org.onebusaway.gtfs.model.Agency;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.Frequency;
import org.onebusaway.gtfs.model.Route;
import org.onebusaway.gtfs.model.ServiceCalendar;
import org.onebusaway.gtfs.model.ServiceCalendarDate;
import org.onebusaway.gtfs.model.ShapePoint;
import org.onebusaway.gtfs.model.Stop;
import org.onebusaway.gtfs.model.StopTime;
import org.onebusaway.gtfs.model.Trip;
import org.onebusaway.gtfs.services.GtfsMutableRelationalDao;
/**
* A in-memory implementation of GtfsRelationalDaoImpl. It's super fast for most
* methods, but only if you have enough memory to load your entire GTFS into
* memory.
*
* @author bdferris
*
*/
public class GtfsRelationalDaoImpl extends GtfsDaoImpl implements
GtfsMutableRelationalDao {
private Map> _tripAgencyIdsByServiceId = null;
private Map> _routesByAgency = null;
private Map> _stopsByStation = null;
private Map> _stopTimesByTrip = null;
private Map> _stopTimesByStop = null;
private Map> _tripsByRoute = null;
private Map> _tripsByBlockId = null;
private Map> _shapePointsByShapeId = null;
private Map> _frequenciesByTrip = null;
private Map> _calendarDatesByServiceId = null;
private Map> _calendarsByServiceId = null;
public void clearAllCaches() {
_tripAgencyIdsByServiceId = clearMap(_tripAgencyIdsByServiceId);
_routesByAgency = clearMap(_routesByAgency);
_stopsByStation = clearMap(_stopsByStation);
_stopTimesByTrip = clearMap(_stopTimesByTrip);
_stopTimesByStop = clearMap(_stopTimesByStop);
_tripsByRoute = clearMap(_tripsByRoute);
_tripsByBlockId = clearMap(_tripsByBlockId);
_shapePointsByShapeId = clearMap(_shapePointsByShapeId);
_frequenciesByTrip = clearMap(_frequenciesByTrip);
_calendarDatesByServiceId = clearMap(_calendarDatesByServiceId);
_calendarsByServiceId = clearMap(_calendarsByServiceId);
}
@Override
public List getTripAgencyIdsReferencingServiceId(AgencyAndId serviceId) {
if (_tripAgencyIdsByServiceId == null) {
Map> agencyIdsByServiceIds = new HashMap>();
for (Trip trip : getAllTrips()) {
AgencyAndId tripId = trip.getId();
String tripAgencyId = tripId.getAgencyId();
AgencyAndId tripServiceId = trip.getServiceId();
Set agencyIds = agencyIdsByServiceIds.get(tripServiceId);
if (agencyIds == null) {
agencyIds = new HashSet();
agencyIdsByServiceIds.put(tripServiceId, agencyIds);
}
agencyIds.add(tripAgencyId);
}
_tripAgencyIdsByServiceId = new HashMap>();
for (Map.Entry> entry : agencyIdsByServiceIds.entrySet()) {
AgencyAndId tripServiceId = entry.getKey();
List agencyIds = new ArrayList(entry.getValue());
Collections.sort(agencyIds);
_tripAgencyIdsByServiceId.put(tripServiceId, agencyIds);
}
}
List agencyIds = _tripAgencyIdsByServiceId.get(serviceId);
if (agencyIds == null)
agencyIds = new ArrayList();
return agencyIds;
}
@Override
public List getRoutesForAgency(Agency agency) {
if (_routesByAgency == null)
_routesByAgency = mapToValueList(getAllRoutes(), "agency", Agency.class);
return list(_routesByAgency.get(agency));
}
@Override
public List getStopsForStation(Stop station) {
if (_stopsByStation == null) {
_stopsByStation = new HashMap>();
for (Stop stop : getAllStops()) {
if (stop.getLocationType() == 0 && stop.getParentStation() != null) {
Stop parentStation = getStopForId(new AgencyAndId(
stop.getId().getAgencyId(), stop.getParentStation()));
List subStops = _stopsByStation.get(parentStation);
if (subStops == null) {
subStops = new ArrayList(2);
_stopsByStation.put(parentStation, subStops);
}
subStops.add(stop);
}
}
}
return list(_stopsByStation.get(station));
}
@Override
public List getAllShapeIds() {
ensureShapePointRelation();
return new ArrayList(_shapePointsByShapeId.keySet());
}
@Override
public List getShapePointsForShapeId(AgencyAndId shapeId) {
ensureShapePointRelation();
return list(_shapePointsByShapeId.get(shapeId));
}
@Override
public List getStopTimesForTrip(Trip trip) {
if (_stopTimesByTrip == null) {
_stopTimesByTrip = mapToValueList(getAllStopTimes(), "trip", Trip.class);
for (List stopTimes : _stopTimesByTrip.values())
Collections.sort(stopTimes);
}
return list(_stopTimesByTrip.get(trip));
}
@Override
public List getStopTimesForStop(Stop stop) {
if (_stopTimesByStop == null)
_stopTimesByStop = mapToValueList(getAllStopTimes(), "stop", Stop.class);
return list(_stopTimesByStop.get(stop));
}
@Override
public List getTripsForRoute(Route route) {
if (_tripsByRoute == null)
_tripsByRoute = mapToValueList(getAllTrips(), "route", Route.class);
return list(_tripsByRoute.get(route));
}
@Override
public List getTripsForBlockId(AgencyAndId blockId) {
if (_tripsByBlockId == null) {
_tripsByBlockId = new HashMap>();
for (Trip trip : getAllTrips()) {
if (trip.getBlockId() != null) {
AgencyAndId bid = new AgencyAndId(trip.getId().getAgencyId(),
trip.getBlockId());
List trips = _tripsByBlockId.get(bid);
if (trips == null) {
trips = new ArrayList();
_tripsByBlockId.put(bid, trips);
}
trips.add(trip);
}
}
}
return list(_tripsByBlockId.get(blockId));
}
@Override
public List getFrequenciesForTrip(Trip trip) {
if (_frequenciesByTrip == null)
_frequenciesByTrip = mapToValueList(getAllFrequencies(), "trip",
Trip.class);
return list(_frequenciesByTrip.get(trip));
}
@Override
public List getCalendarDatesForServiceId(
AgencyAndId serviceId) {
if (_calendarDatesByServiceId == null)
_calendarDatesByServiceId = mapToValueList(getAllCalendarDates(),
"serviceId", AgencyAndId.class);
return list(_calendarDatesByServiceId.get(serviceId));
}
@Override
public ServiceCalendar getCalendarForServiceId(AgencyAndId serviceId) {
if (_calendarsByServiceId == null)
_calendarsByServiceId = mapToValueList(getAllCalendars(), "serviceId",
AgencyAndId.class);
List calendars = list(_calendarsByServiceId.get(serviceId));
switch (calendars.size()) {
case 0:
return null;
case 1:
return calendars.get(0);
}
throw new MultipleCalendarsForServiceIdException(serviceId);
}
/****
* Private Methods
****/
private void ensureShapePointRelation() {
if (_shapePointsByShapeId == null) {
_shapePointsByShapeId = mapToValueList(getAllShapePoints(), "shapeId",
AgencyAndId.class);
for (List shapePoints : _shapePointsByShapeId.values())
Collections.sort(shapePoints);
}
}
private static List list(List list) {
if (list == null)
list = new ArrayList();
return Collections.unmodifiableList(list);
}
@SuppressWarnings("unchecked")
private static Map> mapToValueList(Iterable values,
String property, Class keyType) {
return mapToValueCollection(values, property, keyType,
new ArrayList().getClass());
}
@SuppressWarnings("unchecked")
private static , CIMPL extends C> Map mapToValueCollection(
Iterable values, String property, Class keyType,
Class collectionType) {
Map byKey = new HashMap();
SimplePropertyQuery query = new SimplePropertyQuery(property);
for (V value : values) {
K key = (K) query.invoke(value);
C valuesForKey = byKey.get(key);
if (valuesForKey == null) {
try {
valuesForKey = collectionType.newInstance();
} catch (Exception ex) {
throw new EntityInstantiationException(collectionType, ex);
}
byKey.put(key, valuesForKey);
}
valuesForKey.add(value);
}
return byKey;
}
private Map clearMap(Map map) {
if (map != null)
map.clear();
return null;
}
private static final class SimplePropertyQuery {
private String[] _properties;
public SimplePropertyQuery(String query) {
_properties = query.split("\\.");
}
public Object invoke(Object value) {
for (String property : _properties) {
BeanWrapper wrapper = BeanWrapperFactory.wrap(value);
value = wrapper.getPropertyValue(property);
}
return value;
}
}
}