Package org.onebusaway.transit_data_federation.impl.blocks

Source Code of org.onebusaway.transit_data_federation.impl.blocks.BlockIndexServiceImpl

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

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
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 javax.annotation.PostConstruct;

import org.onebusaway.collections.FactoryMap;
import org.onebusaway.collections.tuple.Pair;
import org.onebusaway.collections.tuple.Tuples;
import org.onebusaway.container.refresh.Refreshable;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.transit_data_federation.impl.RefreshableResources;
import org.onebusaway.transit_data_federation.impl.transit_graph.StopEntryImpl;
import org.onebusaway.transit_data_federation.services.FederatedTransitDataBundle;
import org.onebusaway.transit_data_federation.services.blocks.BlockIndexFactoryService;
import org.onebusaway.transit_data_federation.services.blocks.BlockIndexService;
import org.onebusaway.transit_data_federation.services.blocks.BlockLayoverIndex;
import org.onebusaway.transit_data_federation.services.blocks.BlockLayoverIndexData;
import org.onebusaway.transit_data_federation.services.blocks.BlockSequenceIndex;
import org.onebusaway.transit_data_federation.services.blocks.BlockStopSequenceIndex;
import org.onebusaway.transit_data_federation.services.blocks.BlockStopTimeIndex;
import org.onebusaway.transit_data_federation.services.blocks.BlockTripIndex;
import org.onebusaway.transit_data_federation.services.blocks.BlockTripIndexData;
import org.onebusaway.transit_data_federation.services.blocks.FrequencyBlockStopTimeIndex;
import org.onebusaway.transit_data_federation.services.blocks.FrequencyBlockTripIndex;
import org.onebusaway.transit_data_federation.services.blocks.FrequencyBlockTripIndexData;
import org.onebusaway.transit_data_federation.services.blocks.FrequencyStopTripIndex;
import org.onebusaway.transit_data_federation.services.blocks.HasBlockTrips;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockEntry;
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.StopEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.StopTimeEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.TransitGraphDao;
import org.onebusaway.utility.ObjectSerializationLibrary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BlockIndexServiceImpl implements BlockIndexService {

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

  private FederatedTransitDataBundle _bundle;

  private TransitGraphDao _graphDao;

  private BlockIndexFactoryService _factory;

  private List<BlockTripIndex> _blockTripIndices;

  private Map<String, List<BlockTripIndex>> _blockTripIndicesByAgencyId;

  private Map<AgencyAndId, List<BlockTripIndex>> _blockTripIndicesByRouteId;

  private Map<AgencyAndId, List<BlockTripIndex>> _blockTripIndicesByBlockId;

  private List<BlockLayoverIndex> _blockLayoverIndices;

  private Map<String, List<BlockLayoverIndex>> _blockLayoverIndicesByAgencyId;

  private Map<AgencyAndId, List<BlockLayoverIndex>> _blockLayoverIndicesByRouteId;

  private Map<AgencyAndId, List<BlockLayoverIndex>> _blockLayoverIndicesByBlockId;

  private List<FrequencyBlockTripIndex> _frequencyBlockTripIndices;

  private Map<String, List<FrequencyBlockTripIndex>> _frequencyBlockTripIndicesByAgencyId;

  private Map<AgencyAndId, List<FrequencyBlockTripIndex>> _frequencyBlockTripIndicesByRouteId;

  private Map<AgencyAndId, List<FrequencyBlockTripIndex>> _frequencyBlockTripIndicesByBlockId;

  private List<BlockSequenceIndex> _blockSequenceIndices = Collections.emptyList();

  @Autowired
  public void setBundle(FederatedTransitDataBundle bundle) {
    _bundle = bundle;
  }

  @Autowired
  public void setBlockIndexFactoryService(
      BlockIndexFactoryService blockIndexFactoryService) {
    _factory = blockIndexFactoryService;
  }

  @Autowired
  public void setGraphDao(TransitGraphDao graphDao) {
    _graphDao = graphDao;
  }

  @PostConstruct
  @Refreshable(dependsOn = RefreshableResources.BLOCK_INDEX_DATA)
  public void setup() throws Exception {

    loadBlockTripIndices();
    loadBlockLayoverIndices();
    loadFrequencyBlockTripIndices();
    loadBlockTripIndicesByBlockId();

    loadBlockSequenceIndices();

    loadStopTimeIndices();
    loadStopTripIndices();
  }

  @Override
  public List<BlockTripIndex> getBlockTripIndices() {
    return _blockTripIndices;
  }

  @Override
  public List<BlockTripIndex> getBlockTripIndicesForAgencyId(String agencyId) {
    return list(_blockTripIndicesByAgencyId.get(agencyId));
  }

  @Override
  public List<BlockTripIndex> getBlockTripIndicesForRouteCollectionId(
      AgencyAndId routeCollectionId) {
    return list(_blockTripIndicesByRouteId.get(routeCollectionId));
  }

  @Override
  public List<BlockTripIndex> getBlockTripIndicesForBlock(AgencyAndId blockId) {
    return list(_blockTripIndicesByBlockId.get(blockId));
  }

  @Override
  public List<BlockStopTimeIndex> getStopTimeIndicesForStop(StopEntry stopEntry) {
    return ((StopEntryImpl) stopEntry).getStopTimeIndices();
  }

  @Override
  public List<BlockSequenceIndex> getAllBlockSequenceIndices() {
    return _blockSequenceIndices;
  }

  @Override
  public List<BlockStopSequenceIndex> getStopSequenceIndicesForStop(
      StopEntry stopEntry) {
    return ((StopEntryImpl) stopEntry).getStopTripIndices();
  }

  @Override
  public List<Pair<BlockStopSequenceIndex>> getBlockSequenceIndicesBetweenStops(
      StopEntry fromStop, StopEntry toStop) {

    List<BlockStopSequenceIndex> fromIndices = ((StopEntryImpl) fromStop).getStopTripIndices();
    List<BlockStopSequenceIndex> toIndices = ((StopEntryImpl) toStop).getStopTripIndices();

    Map<BlockSequenceIndex, BlockStopSequenceIndex> fromIndicesBySequence = getBlockStopSequenceIndicesBySequence(fromIndices);
    Map<BlockSequenceIndex, BlockStopSequenceIndex> toIndicesBySequence = getBlockStopSequenceIndicesBySequence(toIndices);

    fromIndicesBySequence.keySet().retainAll(toIndicesBySequence.keySet());

    List<Pair<BlockStopSequenceIndex>> results = new ArrayList<Pair<BlockStopSequenceIndex>>();

    for (Map.Entry<BlockSequenceIndex, BlockStopSequenceIndex> entry : fromIndicesBySequence.entrySet()) {
      BlockSequenceIndex index = entry.getKey();
      BlockStopSequenceIndex fromStopIndex = entry.getValue();
      BlockStopSequenceIndex toStopIndex = toIndicesBySequence.get(index);

      /**
       * If the stops aren't in the requested order, then we don't include the
       * sequence indices in the results
       */
      if (fromStopIndex.getOffset() > toStopIndex.getOffset())
        continue;

      Pair<BlockStopSequenceIndex> pair = Tuples.pair(fromStopIndex,
          toStopIndex);
      results.add(pair);
    }

    return results;
  }
 
  @Override
  public List<BlockLayoverIndex> getBlockLayoverIndices() {
    return _blockLayoverIndices;
  }

  @Override
  public List<BlockLayoverIndex> getBlockLayoverIndicesForAgencyId(
      String agencyId) {
    return list(_blockLayoverIndicesByAgencyId.get(agencyId));
  }

  @Override
  public List<BlockLayoverIndex> getBlockLayoverIndicesForRouteCollectionId(
      AgencyAndId routeCollectionId) {
    return list(_blockLayoverIndicesByRouteId.get(routeCollectionId));
  }

  @Override
  public List<BlockLayoverIndex> getBlockLayoverIndicesForBlock(
      AgencyAndId blockId) {
    return list(_blockLayoverIndicesByBlockId.get(blockId));
  }

  @Override
  public List<FrequencyBlockTripIndex> getFrequencyBlockTripIndices() {
    return _frequencyBlockTripIndices;
  }

  @Override
  public List<FrequencyBlockTripIndex> getFrequencyBlockTripIndicesForAgencyId(
      String agencyId) {
    return list(_frequencyBlockTripIndicesByAgencyId.get(agencyId));
  }

  @Override
  public List<FrequencyBlockTripIndex> getFrequencyBlockTripIndicesForRouteCollectionId(
      AgencyAndId routeCollectionId) {
    return list(_frequencyBlockTripIndicesByRouteId.get(routeCollectionId));
  }

  @Override
  public List<FrequencyBlockTripIndex> getFrequencyBlockTripIndicesForBlock(
      AgencyAndId blockId) {
    return list(_frequencyBlockTripIndicesByBlockId.get(blockId));
  }

  @Override
  public List<FrequencyBlockStopTimeIndex> getFrequencyStopTimeIndicesForStop(
      StopEntry stopEntry) {
    return ((StopEntryImpl) stopEntry).getFrequencyStopTimeIndices();
  }

  @Override
  public List<FrequencyStopTripIndex> getFrequencyStopTripIndicesForStop(
      StopEntry stop) {
    return ((StopEntryImpl) stop).getFrequencyStopTripIndices();
  }

  @Override
  public List<Pair<FrequencyStopTripIndex>> getFrequencyIndicesBetweenStops(
      StopEntry fromStop, StopEntry toStop) {

    List<FrequencyStopTripIndex> fromIndices = getFrequencyStopTripIndicesForStop(fromStop);
    List<FrequencyStopTripIndex> toIndices = getFrequencyStopTripIndicesForStop(toStop);

    Map<FrequencyBlockTripIndex, FrequencyStopTripIndex> fromIndicesBySequence = getFrequencyStopTripIndicesBySequence(fromIndices);
    Map<FrequencyBlockTripIndex, FrequencyStopTripIndex> toIndicesBySequence = getFrequencyStopTripIndicesBySequence(toIndices);

    fromIndicesBySequence.keySet().retainAll(toIndicesBySequence.keySet());

    List<Pair<FrequencyStopTripIndex>> results = new ArrayList<Pair<FrequencyStopTripIndex>>();

    for (Map.Entry<FrequencyBlockTripIndex, FrequencyStopTripIndex> entry : fromIndicesBySequence.entrySet()) {
      FrequencyBlockTripIndex index = entry.getKey();
      FrequencyStopTripIndex fromStopIndex = entry.getValue();
      FrequencyStopTripIndex toStopIndex = toIndicesBySequence.get(index);

      /**
       * If the stops aren't in the requested order, then we don't include the
       * sequence indices in the results
       */
      if (fromStopIndex.getOffset() > toStopIndex.getOffset())
        continue;

      Pair<FrequencyStopTripIndex> pair = Tuples.pair(fromStopIndex,
          toStopIndex);
      results.add(pair);
    }

    return results;
  }

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

  private <T> List<T> list(List<T> list) {
    if (list == null)
      return Collections.emptyList();
    return list;
  }

  /****
   *
   ****/

  private void loadBlockTripIndices() throws IOException,
      ClassNotFoundException {

    File path = _bundle.getBlockTripIndicesPath();

    if (path.exists()) {

      _log.info("loading block trip indices data");

      List<BlockTripIndexData> datas = ObjectSerializationLibrary.readObject(path);

      _blockTripIndices = new ArrayList<BlockTripIndex>(datas.size());
      for (BlockTripIndexData data : datas)
        _blockTripIndices.add(data.createIndex(_graphDao));

      _blockTripIndicesByAgencyId = getBlockTripIndicesByAgencyId(_blockTripIndices);
      _blockTripIndicesByRouteId = getBlockTripsByRouteId(_blockTripIndices);

      _log.info("block indices data loaded");

    } else {

      _blockTripIndices = Collections.emptyList();
      _blockTripIndicesByAgencyId = Collections.emptyMap();
      _blockTripIndicesByRouteId = Collections.emptyMap();
    }
  }

  private void loadBlockLayoverIndices() throws IOException,
      ClassNotFoundException {

    File path = _bundle.getBlockLayoverIndicesPath();

    if (path.exists()) {

      _log.info("loading block layover indices data");

      List<BlockLayoverIndexData> datas = ObjectSerializationLibrary.readObject(path);

      _blockLayoverIndices = new ArrayList<BlockLayoverIndex>(datas.size());
      for (BlockLayoverIndexData data : datas)
        _blockLayoverIndices.add(data.createIndex(_graphDao));

      _blockLayoverIndicesByAgencyId = getBlockTripIndicesByAgencyId(_blockLayoverIndices);
      _blockLayoverIndicesByRouteId = getBlockTripsByRouteId(_blockLayoverIndices);

      _log.info("block layover indices data loaded");

    } else {

      _blockLayoverIndices = Collections.emptyList();
      _blockLayoverIndicesByAgencyId = Collections.emptyMap();
      _blockLayoverIndicesByRouteId = Collections.emptyMap();
    }
  }

  private void loadFrequencyBlockTripIndices() throws IOException,
      ClassNotFoundException {

    File path = _bundle.getFrequencyBlockTripIndicesPath();

    if (path.exists()) {

      _log.info("loading frequency block trip indices data");

      List<FrequencyBlockTripIndexData> datas = ObjectSerializationLibrary.readObject(path);

      _frequencyBlockTripIndices = new ArrayList<FrequencyBlockTripIndex>(
          datas.size());
      for (FrequencyBlockTripIndexData data : datas)
        _frequencyBlockTripIndices.add(data.createIndex(_graphDao));

      _frequencyBlockTripIndicesByAgencyId = getBlockTripIndicesByAgencyId(_frequencyBlockTripIndices);
      _frequencyBlockTripIndicesByRouteId = getBlockTripsByRouteId(_frequencyBlockTripIndices);

      _log.info("block frequency trip indices data loaded");

    } else {

      _frequencyBlockTripIndices = Collections.emptyList();
      _frequencyBlockTripIndicesByAgencyId = Collections.emptyMap();
      _frequencyBlockTripIndicesByRouteId = Collections.emptyMap();
    }
  }

  /****
   *
   ****/

  private <T extends HasBlockTrips> Map<String, List<T>> getBlockTripIndicesByAgencyId(
      List<T> indices) {

    Map<String, List<T>> blocksByAgencyId = new FactoryMap<String, List<T>>(
        new ArrayList<T>());

    for (T blockIndex : indices) {
      Set<String> agencyIds = new HashSet<String>();
      for (BlockTripEntry blockTrip : blockIndex.getTrips())
        agencyIds.add(blockTrip.getTrip().getId().getAgencyId());
      for (String agencyId : agencyIds)
        blocksByAgencyId.get(agencyId).add(blockIndex);
    }
    return blocksByAgencyId;
  }

  private <T extends HasBlockTrips> Map<AgencyAndId, List<T>> getBlockTripsByRouteId(
      List<T> indices) {

    Map<AgencyAndId, List<T>> blocksByRouteId = new FactoryMap<AgencyAndId, List<T>>(
        new ArrayList<T>());

    for (T index : indices) {
      Set<AgencyAndId> routeIds = new HashSet<AgencyAndId>();
      for (BlockTripEntry blockTrip : index.getTrips())
        routeIds.add(blockTrip.getTrip().getRouteCollection().getId());
      for (AgencyAndId routeId : routeIds)
        blocksByRouteId.get(routeId).add(index);
    }
    return blocksByRouteId;
  }

  /****
   *
   ****/

  private void loadBlockTripIndicesByBlockId() {

    _log.info("calculating block trip indices by blockId...");
    long t1 = System.currentTimeMillis();

    _blockTripIndicesByBlockId = new HashMap<AgencyAndId, List<BlockTripIndex>>();
    _blockLayoverIndicesByBlockId = new HashMap<AgencyAndId, List<BlockLayoverIndex>>();
    _frequencyBlockTripIndicesByBlockId = new HashMap<AgencyAndId, List<FrequencyBlockTripIndex>>();

    for (BlockEntry block : _graphDao.getAllBlocks()) {
      List<BlockEntry> list = Arrays.asList(block);
      List<BlockTripIndex> indices = _factory.createTripIndices(list);
      List<BlockLayoverIndex> layoverIndices = _factory.createLayoverIndices(list);
      List<FrequencyBlockTripIndex> frequencyIndices = _factory.createFrequencyTripIndices(list);

      if (!indices.isEmpty())
        _blockTripIndicesByBlockId.put(block.getId(), indices);
      if (!layoverIndices.isEmpty())
        _blockLayoverIndicesByBlockId.put(block.getId(), layoverIndices);
      if (!frequencyIndices.isEmpty())
        _frequencyBlockTripIndicesByBlockId.put(block.getId(), frequencyIndices);
    }

    long t2 = System.currentTimeMillis();
    _log.info("completed calculating block trip indices by blockId: t="
        + (t2 - t1));
  }

  /****
   *
   ****/

  private void loadBlockSequenceIndices() throws IOException,
      ClassNotFoundException {

    _blockSequenceIndices = _factory.createSequenceIndices(_graphDao.getAllBlocks());
  }

  private void loadStopTimeIndices() {

    // Clear any existing indices
    for (StopEntry stop : _graphDao.getAllStops()) {
      StopEntryImpl stopImpl = (StopEntryImpl) stop;
      stopImpl.getStopTimeIndices().clear();
      stopImpl.getFrequencyStopTimeIndices().clear();
    }

    BlockStopTimeIndicesFactory factory = new BlockStopTimeIndicesFactory();
    factory.setVerbose(true);
    List<BlockStopTimeIndex> indices = factory.createIndices(_graphDao.getAllBlocks());

    for (BlockStopTimeIndex index : indices) {
      StopEntryImpl stop = (StopEntryImpl) index.getStop();
      stop.addStopTimeIndex(index);
    }

    List<FrequencyBlockStopTimeIndex> frequencyIndices = factory.createFrequencyIndices(_graphDao.getAllBlocks());

    for (FrequencyBlockStopTimeIndex index : frequencyIndices) {
      StopEntryImpl stop = (StopEntryImpl) index.getStop();
      stop.addFrequencyStopTimeIndex(index);
    }
  }

  private void loadStopTripIndices() {

    // Clear any existing indices
    for (StopEntry stop : _graphDao.getAllStops()) {
      StopEntryImpl stopImpl = (StopEntryImpl) stop;
      stopImpl.getStopTripIndices().clear();
      stopImpl.getFrequencyStopTripIndices().clear();
    }

    for (BlockSequenceIndex index : _blockSequenceIndices) {

      BlockSequence sequence = index.getSequences().get(0);

      int offset = 0;

      for (BlockStopTimeEntry bst : sequence.getStopTimes()) {

        StopTimeEntry stopTime = bst.getStopTime();
        StopEntryImpl stop = (StopEntryImpl) stopTime.getStop();

        BlockStopSequenceIndex blockStopTripIndex = new BlockStopSequenceIndex(
            index, offset);

        stop.addBlockStopTripIndex(blockStopTripIndex);
        offset++;
      }
    }

    for (FrequencyBlockTripIndex index : _frequencyBlockTripIndices) {

      BlockTripEntry trip = index.getTrips().get(0);

      int offset = 0;

      for (BlockStopTimeEntry bst : trip.getStopTimes()) {

        StopTimeEntry stopTime = bst.getStopTime();
        StopEntryImpl stop = (StopEntryImpl) stopTime.getStop();

        FrequencyStopTripIndex stopTripIndex = new FrequencyStopTripIndex(
            index, offset);
        stop.addFrequencyStopTripIndex(stopTripIndex);
        offset++;
      }
    }
  }

  private Map<BlockSequenceIndex, BlockStopSequenceIndex> getBlockStopSequenceIndicesBySequence(
      List<BlockStopSequenceIndex> indices) {

    Map<BlockSequenceIndex, BlockStopSequenceIndex> m = new HashMap<BlockSequenceIndex, BlockStopSequenceIndex>();

    for (BlockStopSequenceIndex index : indices)
      m.put(index.getIndex(), index);

    return m;
  }

  private Map<FrequencyBlockTripIndex, FrequencyStopTripIndex> getFrequencyStopTripIndicesBySequence(
      List<FrequencyStopTripIndex> indices) {

    Map<FrequencyBlockTripIndex, FrequencyStopTripIndex> m = new HashMap<FrequencyBlockTripIndex, FrequencyStopTripIndex>();

    for (FrequencyStopTripIndex index : indices)
      m.put(index.getIndex(), index);

    return m;
  }

}
TOP

Related Classes of org.onebusaway.transit_data_federation.impl.blocks.BlockIndexServiceImpl

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.