Package org.onebusaway.transit_data_federation.impl.beans

Source Code of org.onebusaway.transit_data_federation.impl.beans.StopScheduleBeanServiceImpl$StopTimeBeanComparator

/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
* Copyright (C) 2011 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.transit_data_federation.impl.beans;

import java.util.ArrayList;
import java.util.Collection;
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.SortedMap;
import java.util.TimeZone;
import java.util.TreeMap;

import org.onebusaway.collections.Counter;
import org.onebusaway.collections.FactoryMap;
import org.onebusaway.container.cache.Cacheable;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.calendar.ServiceDate;
import org.onebusaway.transit_data.model.RouteBean;
import org.onebusaway.transit_data.model.StopCalendarDayBean;
import org.onebusaway.transit_data.model.StopCalendarDaysBean;
import org.onebusaway.transit_data.model.StopRouteDirectionScheduleBean;
import org.onebusaway.transit_data.model.StopRouteScheduleBean;
import org.onebusaway.transit_data.model.StopTimeGroupBean;
import org.onebusaway.transit_data.model.StopTimeInstanceBean;
import org.onebusaway.transit_data.model.schedule.FrequencyInstanceBean;
import org.onebusaway.transit_data_federation.model.narrative.TripNarrative;
import org.onebusaway.transit_data_federation.services.AgencyAndIdLibrary;
import org.onebusaway.transit_data_federation.services.AgencyService;
import org.onebusaway.transit_data_federation.services.ExtendedCalendarService;
import org.onebusaway.transit_data_federation.services.beans.RouteBeanService;
import org.onebusaway.transit_data_federation.services.beans.StopScheduleBeanService;
import org.onebusaway.transit_data_federation.services.blocks.BlockIndexService;
import org.onebusaway.transit_data_federation.services.blocks.BlockStopTimeIndex;
import org.onebusaway.transit_data_federation.services.blocks.FrequencyBlockStopTimeIndex;
import org.onebusaway.transit_data_federation.services.blocks.InstanceState;
import org.onebusaway.transit_data_federation.services.narrative.NarrativeService;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockStopTimeEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockTripEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.FrequencyBlockStopTimeEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.FrequencyEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.ServiceIdActivation;
import org.onebusaway.transit_data_federation.services.transit_graph.StopEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.TransitGraphDao;
import org.onebusaway.transit_data_federation.services.transit_graph.TripEntry;
import org.onebusaway.transit_data_federation.services.tripplanner.StopTimeInstance;
import org.onebusaway.utility.text.NaturalStringOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
class StopScheduleBeanServiceImpl implements StopScheduleBeanService {

  private static final int DEFAULT_CONTINUES_AS_THRESHOLD = 7 * 60;

  private static StopTimeBeanComparator _stopTimeComparator = new StopTimeBeanComparator();

  private static FrequencyBeanComparator _frequencyComparator = new FrequencyBeanComparator();

  private static DirectionComparator _directionComparator = new DirectionComparator();

  private static StopRouteScheduleBeanComparator _stopRouteScheduleComparator = new StopRouteScheduleBeanComparator();

  private AgencyService _agencyService;

  private TransitGraphDao _graph;

  private ExtendedCalendarService _calendarService;

  private RouteBeanService _routeBeanService;

  private NarrativeService _narrativeService;

  private BlockIndexService _blockIndexService;

  private int _continuesAsThreshold = DEFAULT_CONTINUES_AS_THRESHOLD;

  @Autowired
  public void setAgencyService(AgencyService agencyService) {
    _agencyService = agencyService;
  }

  @Autowired
  public void setTransitGraphDao(TransitGraphDao graph) {
    _graph = graph;
  }

  @Autowired
  public void setCalendarService(ExtendedCalendarService calendarService) {
    _calendarService = calendarService;
  }

  @Autowired
  public void setRouteBeanService(RouteBeanService routeBeanService) {
    _routeBeanService = routeBeanService;
  }

  @Autowired
  public void setNarrativeService(NarrativeService narrativeService) {
    _narrativeService = narrativeService;
  }

  @Autowired
  public void setBlockIndexService(BlockIndexService blockIndexService) {
    _blockIndexService = blockIndexService;
  }

  /**
   * When determining if one trip "continues as" another, we have a time
   * threshold to determine if a rider is likely to actually stay on that bus.
   * The idea is that if the time delay between the previous trip and the next
   * trip, it's likely that there is a layover in there that the user wouldn't
   * stick around for.
   *
   * @param continuesAsThreshold - time in seconds
   */
  public void setContinuesAsThreshold(int continuesAsThreshold) {
    _continuesAsThreshold = continuesAsThreshold;
  }

  @Cacheable
  public StopCalendarDaysBean getCalendarForStop(AgencyAndId stopId) {

    TimeZone timeZone = _agencyService.getTimeZoneForAgencyId(stopId.getAgencyId());

    StopEntry stopEntry = _graph.getStopEntryForId(stopId);
    Set<ServiceIdActivation> serviceIds = new HashSet<ServiceIdActivation>();

    for (BlockStopTimeIndex index : _blockIndexService.getStopTimeIndicesForStop(stopEntry))
      serviceIds.add(index.getServiceIds());

    for (FrequencyBlockStopTimeIndex index : _blockIndexService.getFrequencyStopTimeIndicesForStop(stopEntry))
      serviceIds.add(index.getServiceIds());

    SortedMap<ServiceDate, Set<ServiceIdActivation>> serviceIdsByDate = getServiceIdsByDate(serviceIds);

    Counter<Set<ServiceIdActivation>> counts = new Counter<Set<ServiceIdActivation>>();
    for (Set<ServiceIdActivation> ids : serviceIdsByDate.values())
      counts.increment(ids);

    int total = counts.size();
    Map<Set<ServiceIdActivation>, Integer> idsToGroup = new HashMap<Set<ServiceIdActivation>, Integer>();
    for (Set<ServiceIdActivation> ids : counts.getSortedKeys())
      idsToGroup.put(ids, total--);

    List<StopCalendarDayBean> beans = new ArrayList<StopCalendarDayBean>(
        serviceIdsByDate.size());
    for (Map.Entry<ServiceDate, Set<ServiceIdActivation>> entry : serviceIdsByDate.entrySet()) {
      StopCalendarDayBean bean = new StopCalendarDayBean();
      ServiceDate serviceDate = entry.getKey();
      Date date = serviceDate.getAsDate(timeZone);
      bean.setDate(date);
      Integer indexId = idsToGroup.get(entry.getValue());
      bean.setGroup(indexId);
      beans.add(bean);
    }

    return new StopCalendarDaysBean(timeZone.getID(), beans);
  }

  @Cacheable
  public List<StopRouteScheduleBean> getScheduledArrivalsForStopAndDate(
      AgencyAndId stopId, ServiceDate date) {

    StopEntry stopEntry = _graph.getStopEntryForId(stopId);

    Map<AgencyAndId, List<StopTimeInstance>> stopTimesByRouteCollectionId = new FactoryMap<AgencyAndId, List<StopTimeInstance>>(
        new ArrayList<StopTimeInstance>());
    Map<AgencyAndId, List<StopTimeInstance>> frequenciesByRouteCollectionId = new FactoryMap<AgencyAndId, List<StopTimeInstance>>(
        new ArrayList<StopTimeInstance>());

    groupStopTimeInstancesByRouteCollectionId(stopEntry, date,
        stopTimesByRouteCollectionId, frequenciesByRouteCollectionId);

    groupFrequencyInstancesByRouteCollectionId(stopEntry, date,
        frequenciesByRouteCollectionId);

    Set<AgencyAndId> routeIds = new HashSet<AgencyAndId>();
    routeIds.addAll(stopTimesByRouteCollectionId.keySet());
    routeIds.addAll(frequenciesByRouteCollectionId.keySet());

    List<StopRouteScheduleBean> beans = new ArrayList<StopRouteScheduleBean>();

    for (AgencyAndId routeId : routeIds) {

      StopRouteScheduleBean routeScheduleBean = new StopRouteScheduleBean();
      beans.add(routeScheduleBean);

      RouteBean route = _routeBeanService.getRouteForId(routeId);
      routeScheduleBean.setRoute(route);

      Map<String, StopTimeByDirectionEntry> stopTimesByDirection = new FactoryMap<String, StopTimeByDirectionEntry>(
          new StopTimeByDirectionEntry());

      List<StopTimeInstance> stopTimesForRoute = stopTimesByRouteCollectionId.get(routeId);

      for (StopTimeInstance sti : stopTimesForRoute) {

        BlockStopTimeEntry bst = sti.getStopTime();
        BlockTripEntry blockTrip = sti.getTrip();
        BlockConfigurationEntry blockConfig = blockTrip.getBlockConfiguration();
        TripEntry trip = blockTrip.getTrip();

        AgencyAndId tripId = trip.getId();
        AgencyAndId serviceId = trip.getServiceId().getId();

        TripNarrative narrative = _narrativeService.getTripForId(tripId);

        StopTimeInstanceBean stiBean = new StopTimeInstanceBean();
        stiBean.setTripId(AgencyAndIdLibrary.convertToString(tripId));
        stiBean.setServiceDate(sti.getServiceDate());
        stiBean.setArrivalTime(sti.getArrivalTime());
        stiBean.setDepartureTime(sti.getDepartureTime());
        stiBean.setServiceId(AgencyAndIdLibrary.convertToString(serviceId));

        stiBean.setArrivalEnabled(bst.getBlockSequence() > 0);
        stiBean.setDepartureEnabled(bst.getBlockSequence() + 1 < blockConfig.getStopTimes().size());

        String directionId = trip.getDirectionId();
        if (directionId == null)
          directionId = "0";

        String tripHeadsign = narrative.getTripHeadsign();

        TripHeadsignStopTimeGroupKey groupKey = new TripHeadsignStopTimeGroupKey(
            tripHeadsign);
        ContinuesAsStopTimeGroupKey continuesAsGroupKey = getContinuesAsGroupKeyForStopTimeInstance(sti);

        StopTimeByDirectionEntry stopTimesForDirection = stopTimesByDirection.get(directionId);

        stopTimesForDirection.addEntry(stiBean, tripHeadsign, groupKey,
            continuesAsGroupKey);
      }

      List<StopTimeInstance> frequenciesForRoute = frequenciesByRouteCollectionId.get(routeId);

      for (StopTimeInstance sti : frequenciesForRoute) {

        BlockStopTimeEntry blockStopTime = sti.getStopTime();
        BlockTripEntry blockTrip = blockStopTime.getTrip();
        TripEntry trip = blockTrip.getTrip();
        BlockConfigurationEntry blockConfig = blockTrip.getBlockConfiguration();

        AgencyAndId tripId = trip.getId();
        AgencyAndId serviceId = trip.getServiceId().getId();

        TripNarrative narrative = _narrativeService.getTripForId(tripId);

        FrequencyInstanceBean bean = new FrequencyInstanceBean();
        bean.setTripId(AgencyAndIdLibrary.convertToString(tripId));
        bean.setServiceDate(sti.getServiceDate());
        bean.setStartTime(sti.getServiceDate()
            + sti.getFrequency().getStartTime() * 1000);
        bean.setEndTime(sti.getServiceDate() + sti.getFrequency().getEndTime()
            * 1000);
        bean.setHeadwaySecs(sti.getFrequency().getHeadwaySecs());
        bean.setServiceId(AgencyAndIdLibrary.convertToString(serviceId));
        bean.setArrivalEnabled(blockStopTime.getBlockSequence() > 0);
        bean.setDepartureEnabled(blockStopTime.getBlockSequence() + 1 < blockConfig.getStopTimes().size());

        String directionId = trip.getDirectionId();
        if (directionId == null)
          directionId = "0";

        StopTimeByDirectionEntry stopTimesForDirection = stopTimesByDirection.get(directionId);
        stopTimesForDirection.addEntry(bean, narrative.getTripHeadsign());
      }

      for (StopTimeByDirectionEntry stopTimesForDirection : stopTimesByDirection.values()) {

        StopRouteDirectionScheduleBean directionBean = new StopRouteDirectionScheduleBean();

        directionBean.getStopTimes().addAll(
            stopTimesForDirection.getStopTimes());

        directionBean.getFrequencies().addAll(
            stopTimesForDirection.getFrequencies());

        String headsign = stopTimesForDirection.getBestHeadsign();
        directionBean.setTripHeadsign(headsign);

        Collections.sort(directionBean.getStopTimes(), _stopTimeComparator);
        Collections.sort(directionBean.getFrequencies(), _frequencyComparator);

        List<StopTimeGroupBean> groups = new ArrayList<StopTimeGroupBean>();

        applyTripHeadsignStopTimeGroups(stopTimesForDirection, groups);
        applyContinuesAsStopTimeGroups(stopTimesForDirection, groups);

        directionBean.setGroups(groups);

        routeScheduleBean.getDirections().add(directionBean);
      }

      Collections.sort(routeScheduleBean.getDirections(), _directionComparator);
    }

    Collections.sort(beans, _stopRouteScheduleComparator);

    return beans;
  }

  /****
   * Private Methods
   ****/

  private SortedMap<ServiceDate, Set<ServiceIdActivation>> getServiceIdsByDate(
      Set<ServiceIdActivation> allServiceIds) {

    SortedMap<ServiceDate, Set<ServiceIdActivation>> serviceIdsByDate = new TreeMap<ServiceDate, Set<ServiceIdActivation>>();
    serviceIdsByDate = FactoryMap.createSorted(serviceIdsByDate,
        new HashSet<ServiceIdActivation>());

    for (ServiceIdActivation serviceIds : allServiceIds) {
      Set<ServiceDate> dates = _calendarService.getServiceDatesForServiceIds(serviceIds);
      for (ServiceDate date : dates) {
        serviceIdsByDate.get(date).add(serviceIds);
      }
    }
    return serviceIdsByDate;
  }

  private static class StopTimeBeanComparator implements
      Comparator<StopTimeInstanceBean> {

    public int compare(StopTimeInstanceBean o1, StopTimeInstanceBean o2) {
      long t1 = o1.getDepartureTime();
      long t2 = o2.getDepartureTime();
      return new Long(t1).compareTo(new Long(t2));
    }
  }

  private static class FrequencyBeanComparator implements
      Comparator<FrequencyInstanceBean> {

    public int compare(FrequencyInstanceBean o1, FrequencyInstanceBean o2) {

      long t1 = o1.getStartTime();
      long t2 = o2.getStartTime();
      return new Long(t1).compareTo(new Long(t2));
    }
  }

  private void groupStopTimeInstancesByRouteCollectionId(StopEntry stopEntry,
      ServiceDate date,
      Map<AgencyAndId, List<StopTimeInstance>> stopTimesByRouteCollectionId,
      Map<AgencyAndId, List<StopTimeInstance>> frequenciesByRouteCollectionId) {

    Map<AgencyAndId, Set<FrequencyEntry>> frequencyLabelsByRouteCollectionId = new FactoryMap<AgencyAndId, Set<FrequencyEntry>>(
        new HashSet<FrequencyEntry>());

    for (BlockStopTimeIndex index : _blockIndexService.getStopTimeIndicesForStop(stopEntry)) {

      ServiceIdActivation serviceIds = index.getServiceIds();

      Set<ServiceDate> serviceDates = _calendarService.getServiceDatesForServiceIds(serviceIds);
      if (!serviceDates.contains(date))
        continue;

      Date serviceDate = date.getAsDate(serviceIds.getTimeZone());

      for (BlockStopTimeEntry stopTime : index.getStopTimes()) {

        BlockTripEntry blockTrip = stopTime.getTrip();
        TripEntry trip = blockTrip.getTrip();
        AgencyAndId routeCollectionId = trip.getRouteCollection().getId();

        FrequencyEntry frequencyLabel = trip.getFrequencyLabel();
        InstanceState state = new InstanceState(serviceDate.getTime(),
            frequencyLabel);
        StopTimeInstance sti = new StopTimeInstance(stopTime, state);

        if (frequencyLabel == null) {
          stopTimesByRouteCollectionId.get(routeCollectionId).add(sti);
        } else if (frequencyLabelsByRouteCollectionId.get(routeCollectionId).add(
            frequencyLabel)) {
          frequenciesByRouteCollectionId.get(routeCollectionId).add(sti);
        }
      }
    }
  }

  private void groupFrequencyInstancesByRouteCollectionId(StopEntry stopEntry,
      ServiceDate date,
      Map<AgencyAndId, List<StopTimeInstance>> frequenciesByRouteCollectionId) {

    for (FrequencyBlockStopTimeIndex index : _blockIndexService.getFrequencyStopTimeIndicesForStop(stopEntry)) {

      ServiceIdActivation serviceIds = index.getServiceIds();

      Set<ServiceDate> serviceDates = _calendarService.getServiceDatesForServiceIds(serviceIds);
      if (!serviceDates.contains(date))
        continue;

      Date serviceDate = date.getAsDate(serviceIds.getTimeZone());

      for (FrequencyBlockStopTimeEntry entry : index.getFrequencyStopTimes()) {

        BlockStopTimeEntry stopTime = entry.getStopTime();

        BlockTripEntry blockTrip = stopTime.getTrip();
        TripEntry trip = blockTrip.getTrip();
        AgencyAndId routeCollectionId = trip.getRouteCollection().getId();
        InstanceState state = new InstanceState(serviceDate.getTime(),
            entry.getFrequency());

        StopTimeInstance sti = new StopTimeInstance(stopTime, state);

        frequenciesByRouteCollectionId.get(routeCollectionId).add(sti);
      }
    }
  }

  private ContinuesAsStopTimeGroupKey getContinuesAsGroupKeyForStopTimeInstance(
      StopTimeInstance instance) {

    BlockTripEntry blockTrip = instance.getTrip();
    AgencyAndId lineId = getContinuesAsLineId(blockTrip);
    return new ContinuesAsStopTimeGroupKey(lineId);
  }

  private AgencyAndId getContinuesAsLineId(BlockTripEntry blockTrip) {

    BlockTripEntry nextTrip = blockTrip.getNextTrip();
    if (nextTrip == null)
      return null;

    TripEntry prevTrip = blockTrip.getTrip();
    AgencyAndId prevLineId = prevTrip.getRouteCollection().getId();
    AgencyAndId nextLineId = nextTrip.getTrip().getRouteCollection().getId();
    if (prevLineId.equals(nextLineId))
      return null;

    List<BlockStopTimeEntry> stopTimes = blockTrip.getStopTimes();
    BlockStopTimeEntry prevStopTime = stopTimes.get(stopTimes.size() - 1);

    List<BlockStopTimeEntry> nextStopTimes = nextTrip.getStopTimes();
    BlockStopTimeEntry nextStopTime = nextStopTimes.get(0);

    int prevTime = prevStopTime.getStopTime().getDepartureTime();
    int nextTime = nextStopTime.getStopTime().getArrivalTime();

    if (nextTime - prevTime > _continuesAsThreshold)
      return null;

    return nextLineId;
  }

  private void applyTripHeadsignStopTimeGroups(
      StopTimeByDirectionEntry stopTimesForDirection,
      List<StopTimeGroupBean> groups) {

    Counter<TripHeadsignStopTimeGroupKey> keyCounts = stopTimesForDirection.getTripHeadsignKeyCounts();
    List<TripHeadsignStopTimeGroupKey> sortedKeys = keyCounts.getSortedKeys();

    for (int i = 0; i < sortedKeys.size() - 1; i++) {

      TripHeadsignStopTimeGroupKey key = sortedKeys.get(i);
      StopTimeGroupBean group = new StopTimeGroupBean();

      String groupId = Integer.toString(groups.size());
      group.setId(groupId);

      String tripHeadsign = key.getTripHeadsign();
      group.setTripHeadsign(tripHeadsign);

      applyGroupIdForGroupKey(stopTimesForDirection, key, groupId);

      groups.add(group);
    }
  }

  private void applyContinuesAsStopTimeGroups(
      StopTimeByDirectionEntry stopTimesForDirection,
      List<StopTimeGroupBean> groups) {

    Counter<ContinuesAsStopTimeGroupKey> keyCounts = stopTimesForDirection.getContinuesAsKeyCounts();
    List<ContinuesAsStopTimeGroupKey> sortedKeys = keyCounts.getSortedKeys();

    for (ContinuesAsStopTimeGroupKey key : sortedKeys) {

      AgencyAndId lineId = key.getLineId();
      if (lineId == null)
        continue;
      StopTimeGroupBean group = new StopTimeGroupBean();

      String groupId = Integer.toString(groups.size());
      group.setId(groupId);

      RouteBean route = _routeBeanService.getRouteForId(lineId);
      group.setContinuesAs(route);

      applyGroupIdForGroupKey(stopTimesForDirection, key, groupId);

      groups.add(group);
    }
  }

  private void applyGroupIdForGroupKey(
      StopTimeByDirectionEntry stopTimesForDirection, Object key, String groupId) {

    List<StopTimeInstanceBean> stopTimesForGroup = stopTimesForDirection.getStopTimesForGroupKey(key);

    for (StopTimeInstanceBean stiBean : stopTimesForGroup) {

      List<String> groupIds = stiBean.getGroupIds();
      if (groupIds == null) {
        groupIds = new ArrayList<String>();
        stiBean.setGroupIds(groupIds);
      }
      groupIds.add(groupId);
    }
  }

  private static class StopRouteScheduleBeanComparator implements
      Comparator<StopRouteScheduleBean> {

    public int compare(StopRouteScheduleBean o1, StopRouteScheduleBean o2) {
      String a = getNameForRoute(o1.getRoute());
      String b = getNameForRoute(o2.getRoute());
      return NaturalStringOrder.compareNatural(a, b);
    }

    private static String getNameForRoute(RouteBean route) {
      String name = route.getShortName();
      if (name == null)
        name = route.getLongName();
      if (name == null)
        name = route.getId();
      return name;
    }
  }

  private static class DirectionComparator implements
      Comparator<StopRouteDirectionScheduleBean> {
    @Override
    public int compare(StopRouteDirectionScheduleBean o1,
        StopRouteDirectionScheduleBean o2) {
      String tripA = o1.getTripHeadsign();
      String tripB = o2.getTripHeadsign();
      if (tripA == null)
        tripA = "";
      if (tripB == null)
        tripB = "";
      return tripA.compareTo(tripB);
    }
  }

  public static class StopTimeByDirectionEntry {

    private List<StopTimeInstanceBean> _stopTimes = new ArrayList<StopTimeInstanceBean>();

    private List<FrequencyInstanceBean> _frequencies = new ArrayList<FrequencyInstanceBean>();

    private Counter<String> _headsigns = new Counter<String>();

    private Counter<TripHeadsignStopTimeGroupKey> _tripHeadsignKeyCounts = new Counter<TripHeadsignStopTimeGroupKey>();

    private Counter<ContinuesAsStopTimeGroupKey> _continuesAsKeyCounts = new Counter<ContinuesAsStopTimeGroupKey>();

    private Map<Object, List<StopTimeInstanceBean>> _stopTimesByGroupKey = new FactoryMap<Object, List<StopTimeInstanceBean>>(
        new ArrayList<StopTimeInstanceBean>());

    public Collection<? extends StopTimeInstanceBean> getStopTimes() {
      return _stopTimes;
    }

    public Collection<FrequencyInstanceBean> getFrequencies() {
      return _frequencies;
    }

    public void addEntry(StopTimeInstanceBean sti, String headsign,
        TripHeadsignStopTimeGroupKey groupKey,
        ContinuesAsStopTimeGroupKey continuesAsGroupKey) {
      _stopTimes.add(sti);
      _headsigns.increment(headsign);
      _tripHeadsignKeyCounts.increment(groupKey);
      _continuesAsKeyCounts.increment(continuesAsGroupKey);
      _stopTimesByGroupKey.get(groupKey).add(sti);
      _stopTimesByGroupKey.get(continuesAsGroupKey).add(sti);
    }

    public void addEntry(FrequencyInstanceBean fi, String headsign) {
      _frequencies.add(fi);

      // We weight the frequency-based headsign count by the estimated number of
      // trips in the interval
      int rangeInSeconds = (int) ((fi.getEndTime() - fi.getStartTime()) / 1000);
      int count = rangeInSeconds / fi.getHeadwaySecs();

      _headsigns.increment(headsign, count);
    }

    public String getBestHeadsign() {
      return _headsigns.getMax();
    }

    public Counter<TripHeadsignStopTimeGroupKey> getTripHeadsignKeyCounts() {
      return _tripHeadsignKeyCounts;
    }

    public Counter<ContinuesAsStopTimeGroupKey> getContinuesAsKeyCounts() {
      return _continuesAsKeyCounts;
    }

    public List<StopTimeInstanceBean> getStopTimesForGroupKey(Object key) {
      return _stopTimesByGroupKey.get(key);
    }
  }

  private static class TripHeadsignStopTimeGroupKey {
    private final String tripHeadsign;

    public TripHeadsignStopTimeGroupKey(String tripHeadsign) {
      this.tripHeadsign = tripHeadsign;
    }

    public String getTripHeadsign() {
      return tripHeadsign;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result
          + ((tripHeadsign == null) ? 0 : tripHeadsign.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      TripHeadsignStopTimeGroupKey other = (TripHeadsignStopTimeGroupKey) obj;
      if (tripHeadsign == null) {
        if (other.tripHeadsign != null)
          return false;
      } else if (!tripHeadsign.equals(other.tripHeadsign))
        return false;
      return true;
    }
  }

  private static class ContinuesAsStopTimeGroupKey {

    private final AgencyAndId _lineId;

    public ContinuesAsStopTimeGroupKey(AgencyAndId lineId) {
      _lineId = lineId;
    }

    public AgencyAndId getLineId() {
      return _lineId;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((_lineId == null) ? 0 : _lineId.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      ContinuesAsStopTimeGroupKey other = (ContinuesAsStopTimeGroupKey) obj;
      if (_lineId == null) {
        if (other._lineId != null)
          return false;
      } else if (!_lineId.equals(other._lineId))
        return false;
      return true;
    }
  }
}
TOP

Related Classes of org.onebusaway.transit_data_federation.impl.beans.StopScheduleBeanServiceImpl$StopTimeBeanComparator

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.