/**
* 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.testing;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
import org.onebusaway.geospatial.services.SphericalGeometryLibrary;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.ShapePoint;
import org.onebusaway.gtfs.model.calendar.CalendarServiceData;
import org.onebusaway.gtfs.model.calendar.LocalizedServiceId;
import org.onebusaway.gtfs.model.calendar.ServiceDate;
import org.onebusaway.transit_data_federation.impl.blocks.BlockIndexFactoryServiceImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.AgencyEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockConfigurationEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockConfigurationEntryImpl.Builder;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockStopTimeEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.BlockTripEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.FrequencyEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.RouteCollectionEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.RouteEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.StopEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.StopTimeEntryImpl;
import org.onebusaway.transit_data_federation.impl.transit_graph.TripEntryImpl;
import org.onebusaway.transit_data_federation.impl.tripplanner.StopTransfers;
import org.onebusaway.transit_data_federation.model.ShapePoints;
import org.onebusaway.transit_data_federation.services.blocks.BlockIndexFactoryService;
import org.onebusaway.transit_data_federation.services.blocks.BlockTripIndex;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.BlockEntry;
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.RouteEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.ServiceIdActivation;
import org.onebusaway.transit_data_federation.services.transit_graph.StopTimeEntry;
import org.onebusaway.transit_data_federation.services.transit_graph.TripEntry;
import org.onebusaway.transit_data_federation.services.tripplanner.StopTransfer;
public class UnitTestingSupport {
private static final DateFormat _format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm");
private static final TimeZone _timeZone = TimeZone.getTimeZone("America/Los_Angeles");
static {
_format.setTimeZone(_timeZone);
}
/****
* Time and Date Methods
****/
public static TimeZone timeZone() {
return _timeZone;
}
/**
* @param source format is "yyyy-MM-dd HH:mm"
* @return
*/
public static Date date(String source) {
try {
return _format.parse(source);
} catch (ParseException ex) {
throw new IllegalStateException(ex);
}
}
public static long dateAsLong(String source) {
return UnitTestingSupport.date(source).getTime();
}
public static String format(Date dateA) {
return UnitTestingSupport._format.format(dateA);
}
public static Date getTimeAsDay(Date t) {
return getTimeAsDay(t.getTime());
}
public static Date getTimeAsDay(long t) {
Calendar cal = Calendar.getInstance();
cal.setTimeZone(timeZone());
cal.setTimeInMillis(t);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
public static final int hourToSec(double hour) {
return (int) (hour * 60 * 60);
}
public static int time(int hour, int minute, int seconds) {
return (hour * 60 + minute) * 60 + seconds;
}
public static int time(int hour, int minute) {
return time(hour, minute, 0);
}
/****
* Entity Factory Methods
****/
public static AgencyEntryImpl agency(String id) {
AgencyEntryImpl agency = new AgencyEntryImpl();
agency.setId(id);
return agency;
}
public static RouteEntryImpl route(String id) {
RouteEntryImpl route = new RouteEntryImpl();
route.setId(aid(id));
return route;
}
public static RouteCollectionEntryImpl routeCollection(String id,
RouteEntry... routes) {
RouteCollectionEntryImpl route = new RouteCollectionEntryImpl();
route.setId(aid(id));
route.setChildren(Arrays.asList(routes));
for (RouteEntry routeEntry : routes) {
((RouteEntryImpl) routeEntry).setParent(route);
}
return route;
}
public static StopEntryImpl stop(String id) {
return stop(id, 0.0, 0.0);
}
public static StopEntryImpl stop(String id, double lat, double lon) {
return new StopEntryImpl(aid(id), lat, lon);
}
public static void addTransfer(StopEntryImpl from, StopEntryImpl to) {
double distance = SphericalGeometryLibrary.distance(from.getStopLocation(),
to.getStopLocation());
StopTransfer transfer = new StopTransfer(to, 0, distance);
List<StopTransfer> transfers = new ArrayList<StopTransfer>();
StopTransfers existing = from.getTransfers();
if (existing != null && existing.getTransfersFromStop() != null)
transfers.addAll(existing.getTransfersFromStop());
transfers.add(transfer);
existing = new StopTransfers(transfers, null);
from.setTransfers(existing);
}
public static BlockEntryImpl block(String id) {
BlockEntryImpl block = new BlockEntryImpl();
block.setId(aid(id));
return block;
}
public static TripEntryImpl trip(String id) {
TripEntryImpl trip = new TripEntryImpl();
trip.setId(aid(id));
return trip;
}
public static TripEntryImpl trip(String id, String serviceId) {
TripEntryImpl trip = trip(id);
trip.setServiceId(new LocalizedServiceId(aid(serviceId), timeZone()));
return trip;
}
public static TripEntryImpl trip(String id, String serviceId,
double totalTripDistance) {
TripEntryImpl trip = trip(id, serviceId);
trip.setTotalTripDistance(totalTripDistance);
return trip;
}
public static TripEntryImpl trip(String id, double totalTripDistance) {
TripEntryImpl trip = trip(id);
trip.setTotalTripDistance(totalTripDistance);
return trip;
}
public static FrequencyEntry frequency(int startTime, int endTime,
int headwaySecs) {
return new FrequencyEntryImpl(startTime, endTime, headwaySecs);
}
public static BlockConfigurationEntry linkBlockTrips(BlockEntryImpl block,
TripEntryImpl... trips) {
return linkBlockTrips(block, null, trips);
}
public static BlockConfigurationEntry linkBlockTrips(BlockEntryImpl block,
List<FrequencyEntry> frequencies, TripEntryImpl... trips) {
List<TripEntry> tripEntries = new ArrayList<TripEntry>();
Set<LocalizedServiceId> serviceIds = new TreeSet<LocalizedServiceId>();
for (int i = 0; i < trips.length; i++) {
TripEntryImpl trip = trips[i];
trip.setBlock(block);
tripEntries.add(trip);
if (trip.getServiceId() != null)
serviceIds.add(trip.getServiceId());
}
Builder builder = BlockConfigurationEntryImpl.builder();
builder.setBlock(block);
builder.setServiceIds(new ServiceIdActivation(
new ArrayList<LocalizedServiceId>(serviceIds),
new ArrayList<LocalizedServiceId>()));
builder.setTrips(tripEntries);
builder.setFrequencies(frequencies);
builder.setTripGapDistances(new double[tripEntries.size()]);
BlockConfigurationEntry configuration = builder.create();
List<BlockConfigurationEntry> configurations = block.getConfigurations();
if (configurations == null) {
configurations = new ArrayList<BlockConfigurationEntry>();
block.setConfigurations(configurations);
}
configurations.add(configuration);
return configuration;
}
public static BlockConfigurationEntry linkBlockTrips(String blockId,
TripEntryImpl... trips) {
return linkBlockTrips(block(blockId), trips);
}
public static BlockConfigurationEntry findBlockConfig(BlockEntry blockEntry,
ServiceIdActivation serviceIds) {
for (BlockConfigurationEntry blockConfig : blockEntry.getConfigurations()) {
if (blockConfig.getServiceIds().equals(serviceIds))
return blockConfig;
}
return null;
}
public static List<BlockTripIndex> blockTripIndices(BlockEntryImpl... blocks) {
List<BlockEntry> list = new ArrayList<BlockEntry>();
for (BlockEntryImpl block : blocks)
list.add(block);
BlockIndexFactoryService factory = new BlockIndexFactoryServiceImpl();
return factory.createTripIndices(list);
}
public static StopTimeEntryImpl addStopTime(TripEntryImpl trip,
StopTimeEntryImpl stopTime) {
List<StopTimeEntry> stopTimes = trip.getStopTimes();
if (stopTimes == null) {
stopTimes = new ArrayList<StopTimeEntry>();
trip.setStopTimes(stopTimes);
}
int sequence = stopTimes.size();
if (!stopTimes.isEmpty()) {
StopTimeEntry prev = stopTimes.get(stopTimes.size() - 1);
stopTime.setAccumulatedSlackTime(prev.getAccumulatedSlackTime()
+ prev.getSlackTime());
}
stopTimes.add(stopTime);
stopTime.setTrip(trip);
stopTime.setSequence(sequence);
return stopTime;
}
public static StopTimeEntryImpl stopTime() {
return new StopTimeEntryImpl();
}
public static StopTimeEntryImpl stopTime(int id, StopEntryImpl stop,
TripEntryImpl trip, int arrivalTime, int departureTime,
double shapeDistTraveled) {
return stopTime(id, stop, trip, arrivalTime, departureTime,
shapeDistTraveled, -1);
}
public static StopTimeEntryImpl stopTime(int id, StopEntryImpl stop,
TripEntryImpl trip, int arrivalTime, int departureTime,
double shapeDistTraveled, int shapeIndex) {
StopTimeEntryImpl stopTime = new StopTimeEntryImpl();
stopTime.setId(id);
stopTime.setStop(stop);
stopTime.setArrivalTime(arrivalTime);
stopTime.setDepartureTime(departureTime);
stopTime.setShapeDistTraveled(shapeDistTraveled);
stopTime.setShapePointIndex(shapeIndex);
if (trip != null)
addStopTime(trip, stopTime);
return stopTime;
}
public static StopTimeEntryImpl stopTime(int id, StopEntryImpl stop,
TripEntryImpl trip, int time, double shapeDistTraveled) {
return stopTime(id, stop, trip, time, time, shapeDistTraveled);
}
public static BlockConfigurationEntry blockConfiguration(BlockEntry block,
ServiceIdActivation serviceIds, TripEntry... trips) {
Builder builder = BlockConfigurationEntryImpl.builder();
builder.setBlock(block);
builder.setServiceIds(serviceIds);
builder.setTrips(Arrays.asList(trips));
builder.setTripGapDistances(new double[trips.length]);
BlockConfigurationEntry blockConfig = builder.create();
BlockEntryImpl blockImpl = (BlockEntryImpl) block;
List<BlockConfigurationEntry> configs = block.getConfigurations();
if (configs == null) {
configs = new ArrayList<BlockConfigurationEntry>();
blockImpl.setConfigurations(configs);
}
configs.add(blockConfig);
for (TripEntry trip : trips) {
if (trip.getBlock() == null)
((TripEntryImpl) trip).setBlock((BlockEntryImpl) block);
}
return blockConfig;
}
public static BlockTripEntryImpl blockTrip(
BlockConfigurationEntry blockConfig, TripEntry trip) {
BlockTripEntryImpl blockTrip = new BlockTripEntryImpl();
blockTrip.setBlockConfiguration(blockConfig);
blockTrip.setTrip(trip);
return blockTrip;
}
public static BlockStopTimeEntryImpl blockStopTime(StopTimeEntry stopTime,
int blockSequence, BlockTripEntry trip) {
return new BlockStopTimeEntryImpl(stopTime, blockSequence, trip, true);
}
public static LocalizedServiceId lsid(String id) {
return new LocalizedServiceId(aid(id), timeZone());
}
public static List<LocalizedServiceId> lsids(String... ids) {
List<LocalizedServiceId> serviceIds = new ArrayList<LocalizedServiceId>();
for (String id : ids)
serviceIds.add(lsid(id));
return serviceIds;
}
public static ServiceIdActivation serviceIds(String... ids) {
return new ServiceIdActivation(lsids(ids), lsids());
}
public static ServiceIdActivation serviceIds(
List<LocalizedServiceId> activeServiceIds,
List<LocalizedServiceId> inactiveServiceIds) {
return new ServiceIdActivation(activeServiceIds, inactiveServiceIds);
}
public static AgencyAndId aid(String id) {
return new AgencyAndId("1", id);
}
public static ShapePoints shapePointsFromLatLons(String id, double... values) {
if (values.length % 2 != 0)
throw new IllegalStateException();
int n = values.length / 2;
double[] lats = new double[n];
double[] lons = new double[n];
double[] distances = new double[n];
double distance = 0;
for (int i = 0; i < n; i++) {
lats[i] = values[i * 2];
lons[i] = values[i * 2 + 1];
if (i > 0) {
distance += SphericalGeometryLibrary.distance(lats[i - 1], lons[i - 1],
lats[i], lons[i]);
}
distances[i] = distance;
}
return shapePoints(id, lats, lons, distances);
}
public static ShapePoints shapePoints(String id, double[] lats,
double[] lons, double[] distTraveled) {
ShapePoints shapePoints = new ShapePoints();
shapePoints.setShapeId(aid(id));
shapePoints.setLats(lats);
shapePoints.setLons(lons);
shapePoints.setDistTraveled(distTraveled);
return shapePoints;
}
public static ShapePoint shapePoint(String id, int sequence, double lat,
double lon) {
ShapePoint point = new ShapePoint();
point.setId(sequence);
point.setSequence(sequence);
point.setLat(lat);
point.setLon(lon);
point.setShapeId(aid(id));
return point;
}
public static void addServiceDates(CalendarServiceData data, String sid,
ServiceDate... serviceDates) {
AgencyAndId serviceId = aid(sid);
LocalizedServiceId lsid = lsid(sid);
data.putTimeZoneForAgencyId(serviceId.getAgencyId(), timeZone());
data.putServiceDatesForServiceId(serviceId, Arrays.asList(serviceDates));
List<Date> dates = new ArrayList<Date>();
for (ServiceDate date : serviceDates) {
dates.add(date.getAsDate(_timeZone));
}
data.putDatesForLocalizedServiceId(lsid, dates);
}
public static void addDates(CalendarServiceData data, String sid,
Date... dates) {
AgencyAndId serviceId = aid(sid);
LocalizedServiceId lsid = lsid(sid);
data.putTimeZoneForAgencyId(serviceId.getAgencyId(), timeZone());
data.putDatesForLocalizedServiceId(lsid, Arrays.asList(dates));
Calendar c = Calendar.getInstance();
c.setTimeZone(timeZone());
List<ServiceDate> serviceDates = new ArrayList<ServiceDate>();
for (Date date : dates) {
c.setTime(date);
ServiceDate serviceDate = new ServiceDate(c);
serviceDates.add(serviceDate);
}
data.putServiceDatesForServiceId(serviceId, serviceDates);
}
}