Package org.onebusaway.uk.atco_cif_to_gtfs_converter

Source Code of org.onebusaway.uk.atco_cif_to_gtfs_converter.AtcoCifToGtfsConverter$StopIdComparator

/**
* Copyright (C) 2012 Google, Inc.
*
* 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.uk.atco_cif_to_gtfs_converter;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import org.onebusaway.csv_entities.CsvEntityReader;
import org.onebusaway.csv_entities.EntityHandler;
import org.onebusaway.csv_entities.schema.AnnotationDrivenEntitySchemaFactory;
import org.onebusaway.csv_entities.schema.DefaultEntitySchemaFactory;
import org.onebusaway.gtfs.impl.GtfsRelationalDaoImpl;
import org.onebusaway.gtfs.model.Agency;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.IdentityBean;
import org.onebusaway.gtfs.model.Route;
import org.onebusaway.gtfs.model.ServiceCalendar;
import org.onebusaway.gtfs.model.ServiceCalendarDate;
import org.onebusaway.gtfs.model.Stop;
import org.onebusaway.gtfs.model.StopTime;
import org.onebusaway.gtfs.model.Trip;
import org.onebusaway.gtfs.model.calendar.ServiceDate;
import org.onebusaway.gtfs.serialization.GtfsEntitySchemaFactory;
import org.onebusaway.gtfs.serialization.GtfsWriter;
import org.onebusaway.gtfs_transformer.factory.EntityRetentionGraph;
import org.onebusaway.uk.atco_cif.AdditionalLocationElement;
import org.onebusaway.uk.atco_cif.AtcoCifException;
import org.onebusaway.uk.atco_cif.AtcoCifParser;
import org.onebusaway.uk.atco_cif.ClusterElement;
import org.onebusaway.uk.atco_cif.JourneyDateRunningElement;
import org.onebusaway.uk.atco_cif.JourneyHeaderElement;
import org.onebusaway.uk.atco_cif.JourneyTimePointElement;
import org.onebusaway.uk.atco_cif.LocationElement;
import org.onebusaway.uk.atco_cif.LocationProvider;
import org.onebusaway.uk.atco_cif.OperatorElement;
import org.onebusaway.uk.atco_cif.RouteDescriptionElement;
import org.onebusaway.uk.atco_cif.VehicleTypeElement;
import org.onebusaway.uk.atco_cif.extensions.NationalExpressLocationGeoDetailElement;
import org.onebusaway.uk.atco_cif.extensions.NationalExpressLocationNameElement;
import org.onebusaway.uk.atco_cif.extensions.NationalExpressOperatorElement;
import org.onebusaway.uk.atco_cif.extensions.NationalExpressRouteDetailsElement;
import org.onebusaway.uk.atco_cif.extensions.greater_manchester.GreaterManchesterTimetableRowListElement;
import org.onebusaway.uk.naptan.csv.NaPTANStop;
import org.onebusaway.uk.parser.ContentHandler;
import org.onebusaway.uk.parser.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AtcoCifToGtfsConverter {

  private static Logger _log = LoggerFactory.getLogger(AtcoCifToGtfsConverter.class);

  private static final int MINUTES_IN_DAY = 24 * 60;

  private AtcoCifParser _parser = new AtcoCifParser();

  private File _inputPath;

  private File _outputPath;

  private String _agencyId = "1";

  private String _agencyName = "Agency Name";

  private String _agencyTimezone = "Europe/London";

  private String _agencyLang = "en";

  private String _agencyUrl = "http://agency.gov/";

  private String _agencyPhone = "";

  private int _vehicleType = -1;

  private Map<AgencyAndId, List<JourneyHeaderElement>> _journeysById = new HashMap<AgencyAndId, List<JourneyHeaderElement>>();

  private Map<String, LocationElement> _locationById = new HashMap<String, LocationElement>();

  private Map<String, AdditionalLocationElement> _additionalLocationById = new HashMap<String, AdditionalLocationElement>();

  private Map<String, NaPTANStop> _stopsByAtcoId = new HashMap<String, NaPTANStop>();

  private Map<String, String> _clusterIdByLocationId = new HashMap<String, String>();

  private Map<String, List<Stop>> _stopsByClusterId = new HashMap<String, List<Stop>>();

  private Map<String, GreaterManchesterTimetableRowListElement> _greaterManchesterRowListsByLocationId = new HashMap<String, GreaterManchesterTimetableRowListElement>();

  private Map<String, NationalExpressLocationNameElement> _nxLocationNamesById = new HashMap<String, NationalExpressLocationNameElement>();

  private Map<String, NationalExpressLocationGeoDetailElement> _nxLocationGeoDetailById = new HashMap<String, NationalExpressLocationGeoDetailElement>();

  private Map<String, NationalExpressOperatorElement> _nxOperatorsById = new HashMap<String, NationalExpressOperatorElement>();

  private Map<String, VehicleTypeElement> _vehicleTypesById = new HashMap<String, VehicleTypeElement>();

  private Map<AgencyAndId, RouteMetadata> _routeMetadataById = new HashMap<AgencyAndId, RouteMetadata>();

  private Map<String, OperatorElement> _operatorsById = new HashMap<String, OperatorElement>();

  private Map<String, String> _serviceDateModificationSuffixByKey = new HashMap<String, String>();

  private GtfsRelationalDaoImpl _dao = new GtfsRelationalDaoImpl();

  private boolean _keepStopsWithNoLocationInfo = false;

  private Set<String> _pruneStopsWithPrefixes = Collections.emptySet();

  private boolean _keepTripsWithMissingStops = false;

  private List<String> _preferredDirectionIdsForRouteDetails = Collections.emptyList();

  private File _naptanCsvPath;

  private Set<String> _stopsWithNoLocationInfo = new HashSet<String>();

  private int _prunedStopsWithNoLocationInfoCount = 0;

  private int _prunedStopTimesCount = 0;

  private int _prunedTripsCount = 0;

  public AtcoCifParser getParser() {
    return _parser;
  }

  public void setInputPath(File inputPath) {
    _inputPath = inputPath;
  }

  public void setOutputPath(File outputPath) {
    _outputPath = outputPath;
  }

  public void setAgencyId(String agencyId) {
    _agencyId = agencyId;
  }

  public void setAgencyName(String agencyName) {
    _agencyName = agencyName;
  }

  public void setAgencyUrl(String agencyUrl) {
    _agencyUrl = agencyUrl;
  }

  public void setAgencyPhone(String agencyPhone) {
    _agencyPhone = agencyPhone;
  }

  public void setAgencyTimezone(String agencyTimezone) {
    _agencyTimezone = agencyTimezone;
  }

  public void setAgencyLang(String agencyLang) {
    _agencyLang = agencyLang;
  }

  public void setVehicleType(int vehicleType) {
    _vehicleType = vehicleType;
  }

  public void setKeepStopsWithNoLocationInfo(boolean keepStopsWithNoLocationInfo) {
    _keepStopsWithNoLocationInfo = keepStopsWithNoLocationInfo;
  }

  public void setPruneStopsWithPrefixes(Set<String> pruneStopsWithPrefixes) {
    _pruneStopsWithPrefixes = pruneStopsWithPrefixes;
  }

  public void setKeepTripsWithMissingStops(boolean keepTripsWithMissingStops) {
    _keepTripsWithMissingStops = keepTripsWithMissingStops;
  }

  public void setPreferredDirectionIdsForRouteDetails(List<String> ids) {
    _preferredDirectionIdsForRouteDetails = ids;
  }

  public void setNaptanCsvPath(File naptanCsvPath) {
    _naptanCsvPath = naptanCsvPath;
  }

  public void run() throws IOException {

    _log.info("Input path: " + _inputPath);
    _log.info("Output path: " + _outputPath);

    loadNaptanDataIfNeeded();

    List<File> paths = new ArrayList<File>();
    getApplicableFiles(_inputPath, paths);

    if (paths.isEmpty()) {
      _log.error("No applicable input files were found!");
      System.exit(-1);
    }

    HandlerImpl handler = new HandlerImpl();
    for (File path : paths) {
      _log.info("parsing file: " + path);
      _parser.parse(path, handler);
    }

    constructGtfs();
    writeGtfs();

    if (_prunedStopsWithNoLocationInfoCount > 0) {
      _log.info(String.format(
          "pruned stops with no location info: %d stops used by %d stop times in %d trips",
          _prunedStopsWithNoLocationInfoCount, _prunedStopTimesCount,
          _prunedTripsCount));
    }
  }

  private void loadNaptanDataIfNeeded() throws IOException {
    if (_naptanCsvPath == null) {
      return;
    }

    CsvEntityReader reader = new CsvEntityReader();
    reader.setInputLocation(_naptanCsvPath);
    AnnotationDrivenEntitySchemaFactory entitySchema = new AnnotationDrivenEntitySchemaFactory();
    entitySchema.addPackageToScan("org.onebusaway.uk.naptan.csv");
    reader.setEntitySchemaFactory(entitySchema);
    reader.addEntityHandler(new EntityHandler() {
      @Override
      public void handleEntity(Object arg0) {
        NaPTANStop stop = (NaPTANStop) arg0;
        _stopsByAtcoId.put(stop.getAtcoCode(), stop);
      }
    });
    reader.readEntities(NaPTANStop.class);

    reader.close();

  }

  private void constructGtfs() {
    constructTrips();
    constructStations();
    pruneTrips();
  }

  private void constructTrips() {
    for (List<JourneyHeaderElement> journies : _journeysById.values()) {
      for (int i = 0; i < journies.size(); ++i) {
        JourneyHeaderElement journey = journies.get(i);
        if (journey.getOperatorId().equals("EU")) {
          continue;
        }
        Trip trip = new Trip();
        String id = journey.getOperatorId() + "-"
            + journey.getJourneyIdentifier();
        if (journies.size() > 1) {
          id += "-" + i;
        }
        trip.setId(new AgencyAndId(journey.getOperatorId(), id));
        trip.setRoute(getRouteForJourney(journey));
        trip.setServiceId(getServiceIdForJourney(journey));

        AgencyAndId routeId = trip.getRoute().getId();
        RouteMetadata metadata = getMetadataForRouteId(routeId);

        String directionName = metadata.getDirectionNameForDirectionId(journey.getRouteDirection());
        if (!isEmpty(directionName)) {
          trip.setTripHeadsign(directionName);
        }
        Integer directionId = metadata.getDirectionIdForDirection(journey.getRouteDirection());
        if (directionId != null) {
          trip.setDirectionId(directionId.toString());
        }

        if (constructTimepoints(journey, trip)) {
          _dao.saveEntity(trip);
        }
      }
    }
  }

  private void constructStations() {
    for (List<Stop> stops : _stopsByClusterId.values()) {
      Collections.sort(stops, new StopIdComparator());
      double lat = 0;
      double lon = 0;
      for (Stop stop : stops) {
        lat += stop.getLat();
        lon += stop.getLon();
      }     
      Stop stop = stops.get(0);
      Stop station = new Stop();
      station.setId(id(stop.getParentStation()));
      station.setName(stop.getName());
      station.setLat(lat / stops.size());
      station.setLon(lon / stops.size());
      station.setLocationType(1);
      _dao.saveEntity(station);
    }
  }

  @SuppressWarnings("unchecked")
  private void pruneTrips() {
    EntityRetentionGraph graph = new EntityRetentionGraph(_dao);
    for (Trip trip : _dao.getAllTrips()) {
      List<StopTime> stopTimes = _dao.getStopTimesForTrip(trip);
      if (stopTimes.size() > 1) {
        graph.retainUp(trip);
      }
    }
    for (Class<?> entityClass : GtfsEntitySchemaFactory.getEntityClasses()) {
      List<Object> objectsToRemove = new ArrayList<Object>();
      for (Object entity : _dao.getAllEntitiesForType(entityClass)) {
        if (!graph.isRetained(entity))
          objectsToRemove.add(entity);
      }
      for (Object toRemove : objectsToRemove)
        _dao.removeEntity((IdentityBean<Serializable>) toRemove);
    }
  }

  private RouteMetadata getMetadataForRouteId(AgencyAndId routeId) {
    RouteMetadata metadata = _routeMetadataById.get(routeId);
    if (metadata == null) {
      metadata = new RouteMetadata();
      _routeMetadataById.put(routeId, metadata);
    }
    return metadata;
  }

  private Route getRouteForJourney(JourneyHeaderElement journey) {
    AgencyAndId routeId = getRouteIdForJourney(journey);
    Route route = _dao.getRouteForId(routeId);
    if (route == null) {
      route = new Route();
      route.setAgency(getAgencyForId(routeId.getAgencyId()));
      route.setId(routeId);
      route.setShortName(journey.getRouteIdentifier());
      route.setType(getRouteTypeForJourney(journey));
      RouteMetadata metaData = _routeMetadataById.get(routeId);
      if (metaData != null) {
        for (String id : _preferredDirectionIdsForRouteDetails) {
          String longName = metaData.getRouteLongNameForDirectionId(id);
          if (longName != null) {
            route.setLongName(longName);
            break;
          }
        }
        for (String id : _preferredDirectionIdsForRouteDetails) {
          String routeUrl = metaData.getRouteUrlForDirectionId(id);
          if (routeUrl != null) {
            route.setUrl(routeUrl);
            break;
          }
        }
      }
      _dao.saveEntity(route);
    }
    return route;
  }

  private AgencyAndId getRouteIdForJourney(JourneyHeaderElement journey) {
    return getRouteId(journey.getOperatorId(), journey.getRouteIdentifier());
  }

  private AgencyAndId getRouteId(String operatorId, String routeId) {
    // Note that we include the operator id in the id portion as well
    // because
    // the route identifiers are not unique by themselves in the output
    // GTFS.
    return new AgencyAndId(operatorId, operatorId + "-" + routeId);
  }

  private Agency getAgencyForId(String id) {
    Agency agency = _dao.getAgencyForId(id);
    if (agency == null) {
      agency = new Agency();
      agency.setId(id);
      agency.setTimezone(_agencyTimezone);
      agency.setLang(_agencyLang);

      OperatorElement operator = _operatorsById.get(id);
      if (operator != null) {
        if (!isEmpty(operator.getShortFormName())) {
          agency.setName(operator.getShortFormName());
        }
        if (!isEmpty(operator.getEnquiryPhone())) {
          agency.setPhone(operator.getEnquiryPhone());
        }
      }
      NationalExpressOperatorElement nxOperator = _nxOperatorsById.get(id);
      if (nxOperator != null) {
        if (!isEmpty(nxOperator.getMarketingName())) {
          agency.setName(nxOperator.getMarketingName());
        }
        if (!isEmpty(nxOperator.getUrl())) {
          agency.setUrl(nxOperator.getUrl());
        }
      }

      if (isEmpty(agency.getName())) {
        agency.setName(_agencyName);
      }
      if (isEmpty(agency.getPhone())) {
        agency.setPhone(_agencyPhone);
      }
      if (isEmpty(agency.getUrl())) {
        agency.setUrl(_agencyUrl);
      }
      _dao.saveEntity(agency);
    }
    return agency;
  }

  private int getRouteTypeForJourney(JourneyHeaderElement journey) {
    String vehicleType = journey.getVehicleType();
    VehicleTypeElement vehicleTypeElement = _vehicleTypesById.get(journey.getVehicleType());

    if (vehicleTypeElement != null) {
      vehicleType = vehicleTypeElement.getDescription();
    }
    String desc = vehicleType.toLowerCase();
    if (desc.equals("bus") || desc.equals("coach")) {
      return 3;
    } else if (desc.equals("heavy rail")) {
      return 2;
    } else if (_vehicleType != -1) {
      return _vehicleType;
    } else {
      throw new AtcoCifException(
          "no defautl VehicleType specified and could not determine GTFS route vehicle type from ATCO-CIF vehicle type description: "
              + desc);
    }
  }

  private AgencyAndId getServiceIdForJourney(JourneyHeaderElement journey) {
    AgencyAndId serviceId = constructServiceIdForJourney(journey);
    ServiceCalendar calendar = _dao.getCalendarForServiceId(serviceId);
    if (calendar == null) {
      calendar = new ServiceCalendar();
      calendar.setServiceId(serviceId);
      calendar.setStartDate(getServiceDate(journey.getStartDate()));
      calendar.setEndDate(getServiceDate(journey.getEndDate()));
      calendar.setMonday(journey.getMonday());
      calendar.setTuesday(journey.getTuesday());
      calendar.setWednesday(journey.getWednesday());
      calendar.setThursday(journey.getThursday());
      calendar.setFriday(journey.getFriday());
      calendar.setSaturday(journey.getSaturday());
      calendar.setSunday(journey.getSunday());
      _dao.saveEntity(calendar);

      for (JourneyDateRunningElement modification : journey.getCalendarModifications()) {
        Date startDate = modification.getStartDate();
        Date endDate = modification.getEndDate();

        java.util.Calendar c = java.util.Calendar.getInstance();
        c.setTime(startDate);

        int exceptionType = modification.getOperationCode() == 1 ? 1 : 2;

        while (true) {
          Date date = c.getTime();
          if (date.after(endDate))
            break;

          ServiceCalendarDate calendarDate = new ServiceCalendarDate();
          calendarDate.setServiceId(serviceId);
          calendarDate.setDate(new ServiceDate(date));
          calendarDate.setExceptionType(exceptionType);
          _dao.saveEntity(calendarDate);

          c.add(Calendar.DAY_OF_YEAR, 1);
        }
      }
      _dao.clearAllCaches();
    }
    return serviceId;
  }

  private ServiceDate getServiceDate(Date date) {
    Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
    c.setTime(date);
    return new ServiceDate(c);
  }

  private AgencyAndId constructServiceIdForJourney(JourneyHeaderElement journey) {
    StringBuilder b = new StringBuilder();
    b.append(getServiceDate(journey.getStartDate()).getAsString());
    b.append('-');
    b.append(getServiceDate(journey.getEndDate()).getAsString());
    b.append('-');
    b.append(journey.getSunday() == 1 ? "S" : "_");
    b.append(journey.getMonday() == 1 ? "M" : "_");
    b.append(journey.getTuesday() == 1 ? "T" : "_");
    b.append(journey.getWednesday() == 1 ? "W" : "_");
    b.append(journey.getThursday() == 1 ? "H" : "_");
    b.append(journey.getFriday() == 1 ? "F" : "_");
    b.append(journey.getSaturday() == 1 ? "S" : "_");
    b.append('-');
    b.append(getServiceDateModificationsSuffix(journey));
    return id(b.toString());
  }

  private String getServiceDateModificationsSuffix(JourneyHeaderElement journey) {
    List<JourneyDateRunningElement> modifications = journey.getCalendarModifications();
    if (modifications.isEmpty()) {
      return "00";
    }

    StringBuilder b = new StringBuilder();
    Collections.sort(modifications);
    for (JourneyDateRunningElement modification : modifications) {
      b.append('|');
      b.append(getServiceDate(modification.getStartDate()).getAsString());
      b.append('-');
      b.append(getServiceDate(modification.getEndDate()).getAsString());
      b.append('-');
      b.append(modification.getOperationCode());
    }
    String key = b.toString();
    String suffix = _serviceDateModificationSuffixByKey.get(key);
    if (suffix == null) {
      DecimalFormat format = new DecimalFormat("00");
      suffix = format.format(_serviceDateModificationSuffixByKey.size() + 1);
      _serviceDateModificationSuffixByKey.put(key, suffix);
    }
    return suffix;
  }

  private boolean constructTimepoints(JourneyHeaderElement journey, Trip trip) {

    normalizeTimes(journey);

    boolean first = true;

    for (JourneyTimePointElement timePoint : journey.getTimePoints()) {
      String stopId = timePoint.getLocationId();
      Stop stop = findStop(stopId);
      if (stop == null && !_keepTripsWithMissingStops) {
        _prunedTripsCount++;
        return false;
      }
    }

    for (JourneyTimePointElement timePoint : journey.getTimePoints()) {
      String stopId = timePoint.getLocationId();
      Stop stop = findStop(stopId);

      /**
       * A NULL stop indicates a stop that has been pruned because it doesn't
       * have location information. We do not produce stop times for these
       * stops.
       */
      if (stop == null) {
        _prunedStopTimesCount++;
        continue;
      }

      StopTime stopTime = new StopTime();
      stopTime.setTrip(trip);
      stopTime.setStop(stop);
      if (timePoint.getArrivalTime() != 0 || timePoint.getDepartureTime() != 0
          || first) {
        stopTime.setArrivalTime(timePoint.getArrivalTime() * 60);
        stopTime.setDepartureTime(timePoint.getDepartureTime() * 60);
      }
      if (!timePoint.isPickUpAllowed()) {
        stopTime.setPickupType(1);
      }
      if (!timePoint.isDropOffAllowed()) {
        stopTime.setDropOffType(1);
      }

      stopTime.setStopSequence(_dao.getAllStopTimes().size());
      _dao.saveEntity(stopTime);
      first = false;
    }
    return true;
  }

  private void normalizeTimes(JourneyHeaderElement journey) {
    List<JourneyTimePointElement> timepoints = journey.getTimePoints();
    if (timepoints.isEmpty()) {
      return;
    }

    int prevDepartureTime = -1;
    int dayOffset = 0;

    for (int i = 0; i < timepoints.size(); ++i) {
      JourneyTimePointElement timepoint = timepoints.get(i);
      int arrivalTime = timepoint.getArrivalTime();
      int departureTime = timepoint.getDepartureTime();

      arrivalTime += dayOffset * MINUTES_IN_DAY;
      while (arrivalTime < prevDepartureTime) {
        arrivalTime += MINUTES_IN_DAY;
        dayOffset++;
      }

      departureTime += dayOffset * MINUTES_IN_DAY;
      while (departureTime < arrivalTime) {
        departureTime += MINUTES_IN_DAY;
        dayOffset++;
      }

      timepoint.setArrivalTime(arrivalTime);
      timepoint.setDepartureTime(departureTime);
      prevDepartureTime = departureTime;
    }
  }

  private Stop findStop(String stopId) {

    for (String prefix : _pruneStopsWithPrefixes) {
      if (stopId.startsWith(prefix)) {
        return null;
      }
    }
    NaPTANStop naptanStop = _stopsByAtcoId.get(stopId);
    if (naptanStop != null) {
      return getNaptanStop(naptanStop);
    }
    LocationElement location = getLocationForId(stopId);
    if (location != null) {
      return getAtcoStop(location);
    }
    GreaterManchesterTimetableRowListElement rowList = _greaterManchesterRowListsByLocationId.get(stopId);
    if (rowList != null) {
      return getGreaterManchesterRowListStop(rowList);
    }
    throw new AtcoCifException("no stop found with id " + stopId);
  }

  private Stop getNaptanStop(NaPTANStop naptanStop) {
    AgencyAndId id = id(naptanStop.getAtcoCode());
    Stop stop = _dao.getStopForId(id);
    if (stop == null) {
      stop = new Stop();
      stop.setId(id);
      stop.setName(naptanStop.getCommonName());
      stop.setLat(naptanStop.getLatitude());
      stop.setLon(naptanStop.getLongitude());
      _dao.saveEntity(stop);
    }
    return stop;
  }

  private LocationElement getLocationForId(String stopId) {
    LocationElement location = _locationById.get(stopId);
    /**
     * I've noticed a strange case where a journey references a stop with an id
     * "blahX" when only a stop with id "blah" exists.
     */
    if (location == null) {
      if (stopId.length() > 1) {
        stopId = stopId.substring(0, stopId.length() - 1);
        location = _locationById.get(stopId);
      }
    }
    return location;
  }

  private Stop getAtcoStop(LocationElement location) {
    String locationId = location.getLocationId();
    AgencyAndId id = id(locationId);
    Stop stop = _dao.getStopForId(id);
    if (stop == null) {
      LocationProvider locationSource = _additionalLocationById.get(locationId);
      if (locationSource == null) {
        throw new AtcoCifException("found location with id=" + locationId
            + " but no additional location information found");
      }

      LocationProvider nxLocationSource = _nxLocationGeoDetailById.get(locationId);
      if (nxLocationSource != null) {
        locationSource = nxLocationSource;
      }

      if (locationSource.getLat() == 0.0 || locationSource.getLon() == 0.0) {
        if (_stopsWithNoLocationInfo.add(locationId)) {
          _log.info("stop with no location: " + locationId);
          _prunedStopsWithNoLocationInfoCount++;
        }
        if (!_keepStopsWithNoLocationInfo) {
          return null;
        }
      }
      String name = location.getName();
      NationalExpressLocationNameElement nxNameElement = _nxLocationNamesById.get(locationId);
      if (nxNameElement != null && !nxNameElement.getShortName().isEmpty()) {
        name = nxNameElement.getShortName();
      }

      stop = new Stop();
      stop.setId(id(locationId));
      stop.setName(name);
      stop.setLat(locationSource.getLat());
      stop.setLon(locationSource.getLon());

      String clusterId = _clusterIdByLocationId.get(locationId);
      if (clusterId != null) {
        AgencyAndId stationId = id(clusterId + "-station");
        stop.setParentStation(stationId.getId());
        List<Stop> stops = _stopsByClusterId.get(clusterId);
        if (stops == null) {
          stops = new ArrayList<Stop>();
          _stopsByClusterId.put(clusterId, stops);
        }
        stops.add(stop);
      }

      _dao.saveEntity(stop);
    }
    return stop;
  }

  private Stop getGreaterManchesterRowListStop(
      GreaterManchesterTimetableRowListElement rowList) {
    AgencyAndId id = id(rowList.getLocationReference());
    Stop stop = _dao.getStopForId(id);
    if (stop == null) {
      stop = new Stop();
      stop.setId(id);
      stop.setName(rowList.getFullLocation());
      _dao.saveEntity(stop);
    }
    return stop;
  }

  private void writeGtfs() throws IOException {
    GtfsWriter writer = new GtfsWriter();
    writer.setOutputLocation(_outputPath);
    DefaultEntitySchemaFactory schemaFactory = new DefaultEntitySchemaFactory();
    schemaFactory.addFactory(GtfsEntitySchemaFactory.createEntitySchemaFactory());
    writer.setEntitySchemaFactory(schemaFactory);
    writer.run(_dao);
  }

  private void getApplicableFiles(File path, List<File> applicableFiles) {
    _log.info("Scanning path: " + path);
    if (path.isDirectory()) {
      _log.info("Directory found...");
      for (File subPath : path.listFiles()) {
        getApplicableFiles(subPath, applicableFiles);
      }
    } else if (path.getName().toLowerCase().endsWith(".cif")) {
      _log.info("CIF File found!");
      applicableFiles.add(path);
    }
  }

  private AgencyAndId id(String id) {
    return new AgencyAndId(_agencyId, id);
  }

  private static final boolean isEmpty(String value) {
    return value == null || value.isEmpty();
  }

  private class HandlerImpl implements ContentHandler {

    @Override
    public void startDocument() {
    }

    @Override
    public void endDocument() {

    }

    @Override
    public void startElement(Element element) {
      if (element instanceof JourneyHeaderElement) {
        JourneyHeaderElement journey = (JourneyHeaderElement) element;
        AgencyAndId journeyId = new AgencyAndId(journey.getOperatorId(),
            journey.getJourneyIdentifier());
        List<JourneyHeaderElement> journies = _journeysById.get(journeyId);
        if (journies == null) {
          journies = new ArrayList<JourneyHeaderElement>();
          _journeysById.put(journeyId, journies);
        }
        journies.add(journey);
        AgencyAndId routeId = getRouteIdForJourney(journey);
        RouteMetadata metadata = getMetadataForRouteId(routeId);
        metadata.addDirection(journey.getRouteDirection());
      } else if (element instanceof LocationElement) {
        LocationElement location = (LocationElement) element;
        _locationById.put(location.getLocationId(), location);
      } else if (element instanceof AdditionalLocationElement) {
        AdditionalLocationElement location = (AdditionalLocationElement) element;
        _additionalLocationById.put(location.getLocationId(), location);
      } else if (element instanceof ClusterElement) {
        ClusterElement cluster = (ClusterElement) element;
        _clusterIdByLocationId.put(cluster.getLocationId(), cluster.getId());
      } else if (element instanceof VehicleTypeElement) {
        VehicleTypeElement vehicle = (VehicleTypeElement) element;
        _vehicleTypesById.put(vehicle.getId(), vehicle);
      } else if (element instanceof RouteDescriptionElement) {
        RouteDescriptionElement route = (RouteDescriptionElement) element;
        AgencyAndId id = new AgencyAndId(route.getOperatorId(),
            route.getOperatorId() + "-" + route.getRouteNumber());
        RouteMetadata metadata = getMetadataForRouteId(id);
        metadata.addRouteDescription(route);
      } else if (element instanceof OperatorElement) {
        OperatorElement operator = (OperatorElement) element;
        OperatorElement existing = _operatorsById.put(operator.getOperatorId(),
            operator);
        if (existing != null) {
          _log.info("!");
        }
      } else if (element instanceof NationalExpressLocationNameElement) {
        NationalExpressLocationNameElement nxNameElement = (NationalExpressLocationNameElement) element;
        _nxLocationNamesById.put(nxNameElement.getLocationId(), nxNameElement);
      } else if (element instanceof NationalExpressLocationGeoDetailElement) {
        NationalExpressLocationGeoDetailElement nxGeoDetailElement = (NationalExpressLocationGeoDetailElement) element;
        _nxLocationGeoDetailById.put(nxGeoDetailElement.getLocationId(),
            nxGeoDetailElement);
      } else if (element instanceof NationalExpressOperatorElement) {
        NationalExpressOperatorElement nxElement = (NationalExpressOperatorElement) element;
        _nxOperatorsById.put(nxElement.getId(), nxElement);
      } else if (element instanceof NationalExpressRouteDetailsElement) {
        NationalExpressRouteDetailsElement details = (NationalExpressRouteDetailsElement) element;
        AgencyAndId routeId = getRouteId(details.getOperatorId(),
            details.getRouteId());
        RouteMetadata metadata = getMetadataForRouteId(routeId);
        metadata.addNXRouteDetails(details);
      } else if (element instanceof GreaterManchesterTimetableRowListElement) {
        GreaterManchesterTimetableRowListElement rowList = (GreaterManchesterTimetableRowListElement) element;
        _greaterManchesterRowListsByLocationId.put(
            rowList.getLocationReference(), rowList);
      }
    }

    @Override
    public void endElement(Element element) {

    }
  }

  private static class StopIdComparator implements Comparator<Stop> {

    @Override
    public int compare(Stop lhs, Stop rhs) {
      return lhs.getId().compareTo(rhs.getId());
    }
  }
}
TOP

Related Classes of org.onebusaway.uk.atco_cif_to_gtfs_converter.AtcoCifToGtfsConverter$StopIdComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.