Package org.onebusaway.transit_data_federation.bundle.tasks.transit_graph

Source Code of org.onebusaway.transit_data_federation.bundle.tasks.transit_graph.FrequencyEntriesFactory

/**
* 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.bundle.tasks.transit_graph;

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.onebusaway.collections.FactoryMap;
import org.onebusaway.collections.MappingLibrary;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.Frequency;
import org.onebusaway.gtfs.services.GtfsRelationalDao;
import org.onebusaway.transit_data_federation.impl.blocks.FrequencyComparator;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockConfigurationEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.FrequencyEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.TransitGraphImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.TripEntryImpl;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockTripEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.FrequencyEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.TripEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class FrequencyEntriesFactory {

  private Logger _log = LoggerFactory.getLogger(FrequencyEntriesFactory.class);

  private GtfsRelationalDao _gtfsDao;

  @Autowired
  public void setGtfsDao(GtfsRelationalDao gtfsDao) {
    _gtfsDao = gtfsDao;
  }

  public void processFrequencies(TransitGraphImpl graph) {

    Map<AgencyAndId, List<FrequencyEntry>> frequenciesByTripId = new HashMap<AgencyAndId, List<FrequencyEntry>>();
    Map<FrequencyRouteLabelKey, List<FrequencyEntry>> frequencyLabelsByKey = new FactoryMap<FrequencyRouteLabelKey, List<FrequencyEntry>>(
        new ArrayList<FrequencyEntry>());

    Collection<Frequency> allFrequencies = _gtfsDao.getAllFrequencies();

    int frequencyIndex = 0;

    for (Frequency frequency : allFrequencies) {

      if (frequencyIndex % 100 == 0)
        _log.info("frequencies: " + (frequencyIndex++) + "/"
            + allFrequencies.size());
      frequencyIndex++;

      processRawFrequency(graph, frequency, frequenciesByTripId,
          frequencyLabelsByKey);
    }

    FrequencyComparator comparator = new FrequencyComparator();
    for (List<FrequencyEntry> list : frequenciesByTripId.values()) {
      Collections.sort(list, comparator);
    }

    applyFrequencyLabelsToTrips(graph, frequencyLabelsByKey);

    int blockIndex = 0;

    Map<AgencyAndId, List<TripEntryImpl>> tripsByBlockId = MappingLibrary.mapToValueList(
        graph.getTrips(), "block.id");

    for (Map.Entry<AgencyAndId, List<TripEntryImpl>> entry : tripsByBlockId.entrySet()) {

      if (blockIndex % 10 == 0)
        _log.info("block: " + blockIndex + "/" + tripsByBlockId.size());
      blockIndex++;

      AgencyAndId blockId = entry.getKey();
      List<TripEntryImpl> tripsInBlock = entry.getValue();

      Map<AgencyAndId, List<FrequencyEntry>> frequenciesAlongBlockByTripId = new HashMap<AgencyAndId, List<FrequencyEntry>>();
      Map<AgencyAndId, FrequencyEntry> frequencyLabelsAlongBlockByTripId = new HashMap<AgencyAndId, FrequencyEntry>();

      for (TripEntryImpl trip : tripsInBlock) {
        List<FrequencyEntry> frequencies = frequenciesByTripId.get(trip.getId());
        if (frequencies != null) {
          frequenciesAlongBlockByTripId.put(trip.getId(), frequencies);
        }
        if (trip.getFrequencyLabel() != null) {
          frequencyLabelsAlongBlockByTripId.put(trip.getId(),
              trip.getFrequencyLabel());
        }
      }

      checkForInvalidFrequencyConfigurations(blockId, tripsInBlock,
          frequenciesAlongBlockByTripId, frequencyLabelsAlongBlockByTripId);

      if (!frequenciesAlongBlockByTripId.isEmpty()) {
        applyFrequenciesToBlockTrips(tripsInBlock,
            frequenciesAlongBlockByTripId);
      } else if (!frequencyLabelsAlongBlockByTripId.isEmpty()) {

      } else {
      }
    }
  }

  private void processRawFrequency(TransitGraphImpl graph, Frequency frequency,
      Map<AgencyAndId, List<FrequencyEntry>> frequenciesByTripId,
      Map<FrequencyRouteLabelKey, List<FrequencyEntry>> frequencyLabelsByKey) {
    AgencyAndId tripId = frequency.getTrip().getId();
    TripEntry trip = graph.getTripEntryForId(tripId);

    FrequencyEntryImpl entry = new FrequencyEntryImpl(frequency.getStartTime(),
        frequency.getEndTime(), frequency.getHeadwaySecs());

    FrequencyRouteLabelKey key = getFrequencyLabelKeyForTrip(frequency, trip);

    if (key != null) {
      frequencyLabelsByKey.get(key).add(entry);
    } else {
      List<FrequencyEntry> frequencies = frequenciesByTripId.get(tripId);

      if (frequencies == null) {
        frequencies = new ArrayList<FrequencyEntry>();
        frequenciesByTripId.put(tripId, frequencies);
      }

      frequencies.add(entry);
    }
  }

  private void checkForInvalidFrequencyConfigurations(AgencyAndId blockId,
      List<TripEntryImpl> tripsInBlock,
      Map<AgencyAndId, List<FrequencyEntry>> frequenciesAlongBlockByTripId,
      Map<AgencyAndId, FrequencyEntry> frequencyLabelsAlongBlockByTripId) {

    if (!frequenciesAlongBlockByTripId.isEmpty()
        && !frequencyLabelsAlongBlockByTripId.isEmpty()) {
      throw new IllegalStateException(
          "A block of trips cannot have trips with both normal Frequency entries and label Frequency entries: blockId="
              + blockId);
    }

    if (!frequenciesAlongBlockByTripId.isEmpty()
        && frequenciesAlongBlockByTripId.size() < tripsInBlock.size()) {
      throw new IllegalStateException(
          "can't have mixture of trips with and without frequencies: blockId="
              + blockId);
    }
  }

  private void applyFrequenciesToBlockTrips(List<TripEntryImpl> tripsInBlock,
      Map<AgencyAndId, List<FrequencyEntry>> frequenciesAlongBlockByTripId) {

    BlockEntryImpl blockEntry = tripsInBlock.get(0).getBlock();
    List<BlockConfigurationEntry> configurations = blockEntry.getConfigurations();
    for (int i = 0; i < configurations.size(); i++) {
      BlockConfigurationEntryImpl blockConfig = (BlockConfigurationEntryImpl) configurations.get(i);
      List<FrequencyEntry> frequencies = computeBlockFrequencies(blockEntry,
          blockConfig.getTrips(), frequenciesAlongBlockByTripId);
      blockConfig.setFrequencies(frequencies);
    }
  }

  private void applyFrequencyLabelsToTrips(TransitGraphImpl graph,
      Map<FrequencyRouteLabelKey, List<FrequencyEntry>> frequencyLabelsByKey) {

    for (TripEntry trip : graph.getAllTrips()) {
      List<FrequencyEntry> applicableFrequencyLabels = getApplicableFrequencyLabelsForTrip(
          frequencyLabelsByKey, trip);
      if (applicableFrequencyLabels.isEmpty()) {
        continue;
      } else if (applicableFrequencyLabels.size() > 1) {
        throw new IllegalStateException(
            "multiple applicable frequency labels for tripId=" + trip.getId()
                + " frequencies=" + applicableFrequencyLabels);
      }

      FrequencyEntry frequencyLabel = applicableFrequencyLabels.get(0);
      ((TripEntryImpl) trip).setFrequencyLabel(frequencyLabel);
    }
  }

  private List<FrequencyEntry> getApplicableFrequencyLabelsForTrip(
      Map<FrequencyRouteLabelKey, List<FrequencyEntry>> frequencyLabelsByKey,
      TripEntry trip) {

    AgencyAndId routeId = trip.getRoute().getId();
    AgencyAndId serviceId = trip.getServiceId().getId();
    String directionId = trip.getDirectionId();
    List<AgencyAndId> stopIds = MappingLibrary.map(trip.getStopTimes(),
        "stop.id");

    FrequencyRouteLabelKey keyA = new FrequencyRouteLabelKey(routeId, serviceId);
    FrequencyDirectionLabelKey keyB = new FrequencyDirectionLabelKey(routeId,
        serviceId, directionId);
    FrequencyStopsLabelKey keyC = new FrequencyStopsLabelKey(routeId,
        serviceId, stopIds);

    List<FrequencyEntry> applicableLabels = new ArrayList<FrequencyEntry>();
    FrequencyRouteLabelKey[] keys = {keyA, keyB, keyC};
    for (FrequencyRouteLabelKey key : keys) {
      List<FrequencyEntry> labels = frequencyLabelsByKey.get(key);
      if (labels == null) {
        continue;
      }
      int startTime = trip.getStopTimes().get(0).getDepartureTime();
      for (FrequencyEntry label : labels) {
        if (label.getStartTime() <= startTime && startTime < label.getEndTime()) {
          applicableLabels.add(label);
        }
      }
    }

    return applicableLabels;
  }

  private FrequencyRouteLabelKey getFrequencyLabelKeyForTrip(
      Frequency frequency, TripEntry trip) {
    AgencyAndId routeId = trip.getRoute().getId();
    AgencyAndId serviceId = trip.getServiceId().getId();

    switch (frequency.getLabelOnly()) {
      // Route
      case 1: {
        return new FrequencyRouteLabelKey(routeId, serviceId);
      }
        // Direction
      case 2: {
        AgencyAndId routeId1 = trip.getRoute().getId();
        AgencyAndId serviceId1 = trip.getServiceId().getId();
        return new FrequencyDirectionLabelKey(routeId1, serviceId1,
            trip.getDirectionId());
      }
        // Stops
      case 3: {
        List<AgencyAndId> stopIds = MappingLibrary.map(trip.getStopTimes(),
            "stop.id");
        return new FrequencyStopsLabelKey(routeId, serviceId, stopIds);
      }
    }
    return null;
  }

  private List<FrequencyEntry> computeBlockFrequencies(BlockEntryImpl block,
      List<BlockTripEntry> trips,
      Map<AgencyAndId, List<FrequencyEntry>> frequenciesAlongBlock) {

    List<FrequencyEntry> frequencies = null;

    for (BlockTripEntry blockTrip : trips) {
      TripEntry trip = blockTrip.getTrip();
      List<FrequencyEntry> potentialFrequencies = frequenciesAlongBlock.get(trip.getId());

      if (frequencies == null) {
        frequencies = potentialFrequencies;
      } else {
        if (!frequencies.equals(potentialFrequencies)) {
          throw new IllegalStateException(
              "frequency-based trips in same block don't have same frequencies: blockId="
                  + block.getId());
        }
      }
    }

    return frequencies;
  }
}
TOP

Related Classes of org.onebusaway.transit_data_federation.bundle.tasks.transit_graph.FrequencyEntriesFactory

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.