Package org.onebusaway.transit_data_federation.impl.blocks

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

/**
* 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.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.onebusaway.container.ConfigurationParameter;
import org.onebusaway.geospatial.model.CoordinateBounds;
import org.onebusaway.geospatial.model.CoordinatePoint;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.transit_data_federation.model.TargetTime;
import org.onebusaway.transit_data_federation.services.ExtendedCalendarService;
import org.onebusaway.transit_data_federation.services.blocks.BlockCalendarService;
import org.onebusaway.transit_data_federation.services.blocks.BlockGeospatialService;
import org.onebusaway.transit_data_federation.services.blocks.BlockInstance;
import org.onebusaway.transit_data_federation.services.blocks.BlockSequenceIndex;
import org.onebusaway.transit_data_federation.services.blocks.BlockStatusService;
import org.onebusaway.transit_data_federation.services.blocks.InstanceState;
import org.onebusaway.transit_data_federation.services.blocks.ServiceIntervalBlock;
import org.onebusaway.transit_data_federation.services.realtime.BlockLocation;
import org.onebusaway.transit_data_federation.services.realtime.BlockLocationService;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.FrequencyEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BlockStatusServiceImpl implements BlockStatusService {

  private BlockCalendarService _blockCalendarService;

  private BlockLocationService _blockLocationService;

  private BlockGeospatialService _blockGeospatialService;

  private ExtendedCalendarService _extendedCalendarService;

  /**
   * When searching for blocks to apply real-time information, we will look back
   * the specified number of seconds for vehicles that are potentially running
   * late.
   *
   * This let's us capture blocks that were scheduled to end X seconds before
   * the left-most edge of the user's search window, but that might be running
   * up to X seconds late.
   */
  private int _runningLateWindow = 30 * 60;

  /**
   * When searching for blocks to apply real-time information, we will look
   * ahead the specified number of seconds for vehicles that are potentially
   * running early.
   *
   * This let's us capture trips that were scheduled to start X seconds after
   * the right-most edge of the user's search window, but that might be running
   * up to X seconds early.
   */
  private int _runningEarlyWindow = 10 * 60;

  @Autowired
  public void setActive(BlockCalendarService activeCalendarService) {
    _blockCalendarService = activeCalendarService;
  }

  @Autowired
  public void setBlockLocationService(BlockLocationService blockLocationService) {
    _blockLocationService = blockLocationService;
  }

  @Autowired
  public void setBlockGeospatialService(
      BlockGeospatialService blockGeospatialService) {
    _blockGeospatialService = blockGeospatialService;
  }

  @Autowired
  public void setExtendedCalendarService(
      ExtendedCalendarService extendedCalendarSerivce) {
    _extendedCalendarService = extendedCalendarSerivce;
  }

  /**
   * When searching for blocks to apply real-time information, we will look back
   * the specified number of seconds for vehicles that are potentially running
   * late.
   *
   * @param runningLateWindowInSeconds
   */
  @ConfigurationParameter
  public void setRunningLateWindow(int runningLateWindowInSeconds) {
    _runningLateWindow = runningLateWindowInSeconds;
  }

  public int getRunningLateWindow() {
    return _runningLateWindow;
  }

  /**
   * When searching for blocks to apply real-time information, we will look
   * ahead the specified number of seconds for vehicles that are potentially
   * running early.
   *
   * @param runningEarlyWindowInSeconds time in seconds
   */
  @ConfigurationParameter
  public void setRunningEarlyWindow(int runningEarlyWindowInSeconds) {
    _runningEarlyWindow = runningEarlyWindowInSeconds;
  }

  public int getRunningEarlyWindow() {
    return _runningEarlyWindow;
  }

  /****
   * {@link BlockStatusService} Interface
   ****/

  @Override
  public Map<BlockInstance, List<BlockLocation>> getBlocks(AgencyAndId blockId,
      long serviceDate, AgencyAndId vehicleId, long time) {

    List<BlockInstance> blockInstances = getBlockInstances(blockId,
        serviceDate, time);

    Map<BlockInstance, List<BlockLocation>> results = new HashMap<BlockInstance, List<BlockLocation>>();

    for (BlockInstance blockInstance : blockInstances) {
      List<BlockLocation> locations = new ArrayList<BlockLocation>();
      computeLocations(blockInstance, vehicleId, time, locations);
      results.put(blockInstance, locations);
    }

    return results;
  }

  @Override
  public BlockLocation getBlockForVehicle(AgencyAndId vehicleId, long time) {
    TargetTime target = new TargetTime(time, time);
    return _blockLocationService.getLocationForVehicleAndTime(vehicleId, target);
  }

  @Override
  public List<BlockLocation> getAllActiveBlocks(long time) {
    List<BlockInstance> instances = _blockCalendarService.getActiveBlocksInTimeRange(
        time, time);
    return getAsLocations(instances, time);
  }

  @Override
  public List<BlockLocation> getActiveBlocksForAgency(String agencyId, long time) {

    List<BlockInstance> instances = _blockCalendarService.getActiveBlocksForAgencyInTimeRange(
        agencyId, time, time);

    return getAsLocations(instances, time);
  }

  @Override
  public List<BlockLocation> getBlocksForRoute(AgencyAndId routeId, long time) {

    long timeFrom = time - _runningLateWindow * 1000;
    long timeTo = time + _runningEarlyWindow * 1000;

    List<BlockInstance> instances = _blockCalendarService.getActiveBlocksForRouteInTimeRange(
        routeId, timeFrom, timeTo);

    return getAsLocations(instances, time);
  }

  @Override
  public List<BlockLocation> getBlocksForBounds(CoordinateBounds bounds,
      long time) {

    long timeFrom = time - _runningLateWindow * 1000;
    long timeTo = time + _runningEarlyWindow * 1000;

    List<BlockInstance> instances = _blockGeospatialService.getActiveScheduledBlocksPassingThroughBounds(
        bounds, timeFrom, timeTo);

    List<BlockLocation> locations = getAsLocations(instances, time);
    List<BlockLocation> inRange = new ArrayList<BlockLocation>();
    for (BlockLocation location : locations) {
      CoordinatePoint p = location.getLocation();
      if (p != null && bounds.contains(p))
        inRange.add(location);
    }

    return inRange;
  }

  @Override
  public Map<BlockInstance, List<List<BlockLocation>>> getBlocksForIndex(
      BlockSequenceIndex index, List<Date> timestamps) {

    List<BlockInstance> instances = getBlockInstancesForIndexAndTimestamps(
        index, timestamps);

    Map<BlockInstance, List<List<BlockLocation>>> results = new HashMap<BlockInstance, List<List<BlockLocation>>>();

    for (BlockInstance instance : instances) {
      getBlockLocationsForInstanceAndTimestamps(instance, timestamps, results);
    }

    return results;
  }

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

  private List<BlockInstance> getBlockInstances(AgencyAndId blockId,
      long serviceDate, long time) {

    if (serviceDate != 0) {
      BlockInstance blockInstance = _blockCalendarService.getBlockInstance(
          blockId, serviceDate);
      if (blockInstance == null)
        return Collections.emptyList();
      BlockConfigurationEntry blockConfig = blockInstance.getBlock();
      if (blockConfig.getFrequencies() == null)
        return Arrays.asList(blockInstance);

      List<BlockInstance> instances = new ArrayList<BlockInstance>();
      for (FrequencyEntry frequency : blockConfig.getFrequencies())
        instances.add(new BlockInstance(blockConfig,
            blockInstance.getServiceDate(), frequency));
      return instances;
    } else {

      List<BlockInstance> instances = _blockCalendarService.getActiveBlocks(
          blockId, time, time);

      if (instances.isEmpty()) {
        instances = _blockCalendarService.getClosestActiveBlocks(blockId, time);
      }

      return instances;
    }
  }

  private List<BlockLocation> getAsLocations(Iterable<BlockInstance> instances,
      long time) {
    List<BlockLocation> locations = new ArrayList<BlockLocation>();
    for (BlockInstance instance : instances)
      computeLocations(instance, null, time, locations);
    return locations;
  }

  /**
   *
   * @param instance
   * @param vehicleId optional filter on location results. Can be null.
   * @param time
   * @param results
   */
  private void computeLocations(BlockInstance instance, AgencyAndId vehicleId,
      long time, List<BlockLocation> results) {

    if (instance == null)
      return;

    TargetTime target = new TargetTime(time, time);

    // Try real-time trips first
    List<BlockLocation> locations = _blockLocationService.getLocationsForBlockInstance(
        instance, target);

    if (!locations.isEmpty()) {

      if (vehicleId == null) {
        results.addAll(locations);
      } else {
        for (BlockLocation location : locations)
          if (vehicleId.equals(location.getVehicleId()))
            results.add(location);
      }

    } else {

      // If no real-time trips are available and no vehicle id was specified,
      // use scheduled trips
      if (vehicleId == null) {
        BlockLocation location = _blockLocationService.getScheduledLocationForBlockInstance(
            instance, time);

        if (location != null && location.isInService())
          results.add(location);
      }
    }
  }

  private List<BlockInstance> getBlockInstancesForIndexAndTimestamps(
      BlockSequenceIndex index, List<Date> timestamps) {

    Date tFrom = timestamps.get(0);
    Date tTo = timestamps.get(timestamps.size() - 1);

    ServiceIntervalBlock serviceIntervalBlock = index.getServiceIntervalBlock();
    List<BlockSequence> sequences = index.getSequences();

    Collection<Date> serviceDates = _extendedCalendarService.getServiceDatesWithinRange(
        index.getServiceIds(), serviceIntervalBlock.getRange(), tFrom, tTo);

    List<BlockInstance> instances = new ArrayList<BlockInstance>();

    for (Date serviceDate : serviceDates) {

      int effectiveFromTime = (int) ((tFrom.getTime() - serviceDate.getTime()) / 1000);
      int effectiveToTime = (int) ((tTo.getTime() - serviceDate.getTime()) / 1000);

      int indexFrom = Arrays.binarySearch(
          serviceIntervalBlock.getMaxArrivals(), effectiveFromTime);
      int indexTo = Arrays.binarySearch(
          serviceIntervalBlock.getMinDepartures(), effectiveToTime);

      if (indexFrom < 0)
        indexFrom = -(indexFrom + 1);
      if (indexTo < 0)
        indexTo = -(indexTo + 1);

      InstanceState state = new InstanceState(serviceDate.getTime());

      for (int i = indexFrom; i < indexTo; i++) {

        BlockSequence sequence = sequences.get(i);
        BlockConfigurationEntry blockConfig = sequence.getBlockConfig();
        BlockInstance instance = new BlockInstance(blockConfig, state);
        instances.add(instance);
      }
    }
    return instances;
  }

  private void getBlockLocationsForInstanceAndTimestamps(
      BlockInstance instance, List<Date> timestamps,
      Map<BlockInstance, List<List<BlockLocation>>> results) {

    Map<AgencyAndId, List<BlockLocation>> locations = _blockLocationService.getLocationsForBlockInstance(
        instance, timestamps, System.currentTimeMillis());

    if (locations.isEmpty()) {
      List<List<BlockLocation>> empty = Collections.emptyList();
      results.put(instance, empty);
    } else {
      List<List<BlockLocation>> asList = new ArrayList<List<BlockLocation>>(
          locations.values());
      results.put(instance, asList);
    }
  }
}
TOP

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

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.