/**
* 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.realtime.api;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.onebusaway.gtfs.model.AgencyAndId;
/**
* Vehicle location records are the key data structure for passing real-time
* location data about a transit vehicle from an external data source into
* OneBusAway. It tries to capture a variety of fields that might be present in
* an AVL stream:
*
* <ul>
* <li>block id</li>
* <li>trip id</li>
* <li>vehicle id</li>
* <li>location</li>
* <li>schedule adherence</li>
* <li>arrival data relative to a timepoint</li>
* </ul>
*
* Not all of these fields will necessarily be set by the AVL source, so we may
* have to be flexible in how we process the data.
*
* @author bdferris
* @see VehicleLocationListener
*/
public class VehicleLocationRecord implements Serializable {
private static final long serialVersionUID = 1L;
private long serviceDate;
private AgencyAndId blockId;
private AgencyAndId tripId;
private AgencyAndId vehicleId;
private long timeOfRecord;
private long timeOfLocationUpdate;
/**
* schedule deviation, in seconds, (+deviation is late, -deviation is early)
*/
private double scheduleDeviation = Double.NaN;
private double distanceAlongBlock = Double.NaN;
private double currentLocationLat = Double.NaN;
private double currentLocationLon = Double.NaN;
/**
* In degrees, 0º is East, 90º is North, 180º is West, and 270º is South
*/
private double currentOrientation = Double.NaN;
private List<TimepointPredictionRecord> timepointPredictions;
private EVehiclePhase phase;
private String status;
public VehicleLocationRecord() {
}
public VehicleLocationRecord(VehicleLocationRecord r) {
this.blockId = r.blockId;
this.currentLocationLat = r.currentLocationLat;
this.currentLocationLon = r.currentLocationLon;
this.currentOrientation = r.currentOrientation;
this.timeOfRecord = r.timeOfRecord;
this.timeOfLocationUpdate = r.timeOfLocationUpdate;
this.distanceAlongBlock = r.distanceAlongBlock;
this.scheduleDeviation = r.scheduleDeviation;
this.serviceDate = r.serviceDate;
this.tripId = r.tripId;
this.vehicleId = r.vehicleId;
List<TimepointPredictionRecord> timepointPredictions = r.getTimepointPredictions();
if (timepointPredictions != null) {
List<TimepointPredictionRecord> dup = new ArrayList<TimepointPredictionRecord>(
timepointPredictions.size());
for (TimepointPredictionRecord tpr : timepointPredictions)
dup.add(new TimepointPredictionRecord(tpr));
this.timepointPredictions = dup;
}
}
public long getServiceDate() {
return serviceDate;
}
public void setServiceDate(long serviceDate) {
this.serviceDate = serviceDate;
}
public AgencyAndId getBlockId() {
return blockId;
}
public void setBlockId(AgencyAndId blockId) {
this.blockId = blockId;
}
public AgencyAndId getTripId() {
return tripId;
}
public void setTripId(AgencyAndId tripId) {
this.tripId = tripId;
}
public AgencyAndId getVehicleId() {
return vehicleId;
}
public void setVehicleId(AgencyAndId vehicleId) {
this.vehicleId = vehicleId;
}
/**
*
* @return time when the vehicle location record was made, in unix-time (ms)
*/
public long getTimeOfRecord() {
return timeOfRecord;
}
/**
*
* @param timeOfRecord time when the vehicle location record was made, in
* unix-time (ms)
*/
public void setTimeOfRecord(long timeOfRecord) {
this.timeOfRecord = timeOfRecord;
}
/**
*
* @return time when the last vehicle location update made, in unix-time (ms)
*/
public long getTimeOfLocationUpdate() {
return timeOfLocationUpdate;
}
public void setTimeOfLocationUpdate(long timeOfLocationUpdate) {
this.timeOfLocationUpdate = timeOfLocationUpdate;
}
/**
* @return true if schedule deviation information has been provided
*/
public boolean isScheduleDeviationSet() {
return !Double.isNaN(scheduleDeviation);
}
/**
*
* @return schedule deviation, in seconds, (+deviation is late, -deviation is
* early)
*/
public double getScheduleDeviation() {
return scheduleDeviation;
}
/**
*
* @param scheduleDeviation - in seconds (+deviation is late, -deviation is
* early)
*/
public void setScheduleDeviation(double scheduleDeviation) {
this.scheduleDeviation = scheduleDeviation;
}
public boolean isDistanceAlongBlockSet() {
return !Double.isNaN(distanceAlongBlock);
}
/**
*
* @return the distance traveled along the block in meters, or NaN if not set
*/
public double getDistanceAlongBlock() {
return distanceAlongBlock;
}
/**
*
* @param distanceAlongBlock distance traveled along the block in meters, or
* NaN if not set
*/
public void setDistanceAlongBlock(double distanceAlongBlock) {
this.distanceAlongBlock = distanceAlongBlock;
}
public boolean isCurrentLocationSet() {
return !(Double.isNaN(currentLocationLat) || Double.isNaN(currentLocationLon));
}
public double getCurrentLocationLat() {
return currentLocationLat;
}
public void setCurrentLocationLat(double currentLocationLat) {
this.currentLocationLat = currentLocationLat;
}
public double getCurrentLocationLon() {
return currentLocationLon;
}
public void setCurrentLocationLon(double currentLocationLon) {
this.currentLocationLon = currentLocationLon;
}
public boolean isCurrentOrientationSet() {
return !Double.isNaN(currentOrientation);
}
/**
* In degrees, 0º is East, 90º is North, 180º is West, and 270º is South
*/
public double getCurrentOrientation() {
return currentOrientation;
}
public void setCurrentOrientation(double currentOrientation) {
this.currentOrientation = currentOrientation;
}
public List<TimepointPredictionRecord> getTimepointPredictions() {
return timepointPredictions;
}
public void setTimepointPredictions(
List<TimepointPredictionRecord> timepointPredictions) {
this.timepointPredictions = timepointPredictions;
}
public EVehiclePhase getPhase() {
return phase;
}
public void setPhase(EVehiclePhase phase) {
this.phase = phase;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
@Override
public String toString() {
StringBuilder b = new StringBuilder();
b.append("VehicleLocationRecord:");
if (blockId != null)
b.append(" blockId=").append(blockId);
if (tripId != null)
b.append(" tripId").append(tripId);
if (serviceDate != 0)
b.append(" serviceDate=").append(serviceDate);
if (timeOfRecord != 0)
b.append(" time=").append(timeOfRecord);
if (vehicleId != null)
b.append(" vehicleId=").append(vehicleId);
if (isScheduleDeviationSet())
b.append(" scheduleDeviation=").append(scheduleDeviation);
if (isDistanceAlongBlockSet())
b.append(" distanceAlongBlock=").append(distanceAlongBlock);
if (isCurrentLocationSet())
b.append(" currentLocation=").append(currentLocationLat).append(" ").append(
currentLocationLon);
if (isCurrentOrientationSet())
b.append(" currentOrientation=").append(currentOrientation);
if (phase != null)
b.append(" phase=").append(phase);
if (status != null)
b.append(" status=").append(status);
return b.toString();
}
}