/** * 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.impl.reporting; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.onebusaway.collections.tuple.T2; import org.onebusaway.exceptions.NoSuchStopServiceException; import org.onebusaway.geospatial.model.CoordinatePoint; import org.onebusaway.gtfs.model.AgencyAndId; import org.onebusaway.transit_data.model.ListBean; import org.onebusaway.transit_data.model.StopTimeInstanceBean; import org.onebusaway.transit_data.model.problems.EProblemReportStatus; import org.onebusaway.transit_data.model.problems.ETripProblemGroupBy; import org.onebusaway.transit_data.model.problems.PlannedTripProblemReportBean; import org.onebusaway.transit_data.model.problems.StopProblemReportBean; import org.onebusaway.transit_data.model.problems.StopProblemReportQueryBean; import org.onebusaway.transit_data.model.problems.StopProblemReportSummaryBean; import org.onebusaway.transit_data.model.problems.TripProblemReportBean; import org.onebusaway.transit_data.model.problems.TripProblemReportQueryBean; import org.onebusaway.transit_data.model.problems.TripProblemReportSummaryBean; import org.onebusaway.transit_data.model.tripplanning.ConstraintsBean; import org.onebusaway.transit_data.model.tripplanning.TransitLocationBean; import org.onebusaway.transit_data_federation.services.AgencyAndIdLibrary; import org.onebusaway.transit_data_federation.services.ArrivalAndDepartureQuery; import org.onebusaway.transit_data_federation.services.ArrivalAndDepartureService; import org.onebusaway.transit_data_federation.services.beans.StopBeanService; import org.onebusaway.transit_data_federation.services.beans.StopTimeBeanService; import org.onebusaway.transit_data_federation.services.beans.TripBeanService; import org.onebusaway.transit_data_federation.services.blocks.BlockInstance; import org.onebusaway.transit_data_federation.services.blocks.BlockStatusService; import org.onebusaway.transit_data_federation.services.realtime.ArrivalAndDepartureInstance; import org.onebusaway.transit_data_federation.services.realtime.BlockLocation; import org.onebusaway.transit_data_federation.services.reporting.UserReportingDao; import org.onebusaway.transit_data_federation.services.reporting.UserReportingService; import org.onebusaway.transit_data_federation.services.transit_graph.BlockEntry; import org.onebusaway.transit_data_federation.services.transit_graph.StopEntry; import org.onebusaway.transit_data_federation.services.transit_graph.TransitGraphDao; import org.onebusaway.transit_data_federation.services.transit_graph.TripEntry; import org.onebusaway.transit_data_federation.services.tripplanner.StopTimeInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component class UserReportingServiceImpl implements UserReportingService { private UserReportingDao _userReportingDao; private TransitGraphDao _graph; private BlockStatusService _blockStatusService; private ArrivalAndDepartureService _arrivalAndDepartureService; private TripBeanService _tripBeanService; private StopBeanService _stopBeanService; private StopTimeBeanService _stopTimeBeanService; @Autowired public void setUserReportingDao(UserReportingDao userReportingDao) { _userReportingDao = userReportingDao; } @Autowired public void setGrah(TransitGraphDao graph) { _graph = graph; } @Autowired public void setBlockStatusService(BlockStatusService blockStatusService) { _blockStatusService = blockStatusService; } @Autowired public void setArrivalAndDepartureService( ArrivalAndDepartureService arrivalAndDepartureService) { _arrivalAndDepartureService = arrivalAndDepartureService; } @Autowired public void setTripBeanService(TripBeanService tripBeanService) { _tripBeanService = tripBeanService; } @Autowired public void setStopBeanService(StopBeanService stopBeanService) { _stopBeanService = stopBeanService; } @Autowired public void setStopTimeBeanService(StopTimeBeanService stopTimeBeanService) { _stopTimeBeanService = stopTimeBeanService; } @Override public void reportProblemWithStop(StopProblemReportBean problem) { StopProblemReportRecord record = new StopProblemReportRecord(); String stopId = problem.getStopId(); if (stopId != null) record.setStopId(AgencyAndIdLibrary.convertFromString(stopId)); record.setTime(problem.getTime()); record.setCode(problem.getCode()); record.setUserComment(problem.getUserComment()); if (!Double.isNaN(problem.getUserLat())) record.setUserLat(problem.getUserLat()); if (!Double.isNaN(problem.getUserLon())) record.setUserLon(problem.getUserLon()); if (!Double.isNaN(problem.getUserLocationAccuracy())) record.setUserLocationAccuracy(problem.getUserLocationAccuracy()); record.setStatus(problem.getStatus()); _userReportingDao.saveOrUpdate(record); } @Override public void reportProblemWithTrip(TripProblemReportBean problem) { AgencyAndId tripId = AgencyAndIdLibrary.convertFromString(problem.getTripId()); TripEntry trip = _graph.getTripEntryForId(tripId); if (trip == null) return; BlockEntry block = trip.getBlock(); TripProblemReportRecord record = new TripProblemReportRecord(); record.setCode(problem.getCode()); record.setServiceDate(problem.getServiceDate()); String vehicleId = problem.getVehicleId(); if (vehicleId != null) record.setVehicleId(AgencyAndIdLibrary.convertFromString(vehicleId)); String stopId = problem.getStopId(); if (stopId != null) record.setStopId(AgencyAndIdLibrary.convertFromString(stopId)); record.setTime(problem.getTime()); record.setTripId(tripId); record.setBlockId(block.getId()); record.setUserComment(problem.getUserComment()); if (problem.getUserLat() != null && !Double.isNaN(problem.getUserLat())) record.setUserLat(problem.getUserLat()); if (problem.getUserLon() != null && !Double.isNaN(problem.getUserLon())) record.setUserLon(problem.getUserLon()); if (problem.getUserLocationAccuracy() != null && !Double.isNaN(problem.getUserLocationAccuracy())) record.setUserLocationAccuracy(problem.getUserLocationAccuracy()); record.setUserOnVehicle(problem.isUserOnVehicle()); record.setUserVehicleNumber(problem.getUserVehicleNumber()); Map<BlockInstance, List<BlockLocation>> locationsByInstance = _blockStatusService.getBlocks( block.getId(), problem.getServiceDate(), record.getVehicleId(), problem.getTime()); BlockInstance blockInstance = getBestBlockInstance(locationsByInstance.keySet()); if (blockInstance != null) { List<BlockLocation> blockLocations = locationsByInstance.get(blockInstance); BlockLocation blockLocation = getBestLocation(blockLocations, problem); if (blockLocation != null) { record.setPredicted(blockLocation.isPredicted()); if (blockLocation.isDistanceAlongBlockSet()) record.setDistanceAlongBlock(blockLocation.getDistanceAlongBlock()); if (blockLocation.isScheduleDeviationSet()) record.setScheduleDeviation(blockLocation.getScheduleDeviation()); CoordinatePoint p = blockLocation.getLocation(); if (p != null) { record.setVehicleLat(p.getLat()); record.setVehicleLon(p.getLon()); } record.setMatchedVehicleId(blockLocation.getVehicleId()); } } record.setStatus(problem.getStatus()); _userReportingDao.saveOrUpdate(record); } @Override public ListBean<StopProblemReportSummaryBean> getStopProblemReportSummaries( StopProblemReportQueryBean query) { List<T2<AgencyAndId, Integer>> records = _userReportingDao.getStopProblemReportSummaries( query.getAgencyId(), query.getTimeFrom(), query.getTimeTo(), query.getStatus()); List<StopProblemReportSummaryBean> beans = new ArrayList<StopProblemReportSummaryBean>( records.size()); for (T2<AgencyAndId, Integer> record : records) { AgencyAndId stopId = record.getFirst(); Integer count = record.getSecond(); StopProblemReportSummaryBean bean = new StopProblemReportSummaryBean(); bean.setStop(_stopBeanService.getStopForId(stopId)); bean.setStatus(query.getStatus()); bean.setCount(count); beans.add(bean); } return new ListBean<StopProblemReportSummaryBean>(beans, false); } @Override public ListBean<TripProblemReportSummaryBean> getTripProblemReportSummaries( TripProblemReportQueryBean query, ETripProblemGroupBy groupBy) { List<T2<Object, Integer>> records = _userReportingDao.getTripProblemReportSummaries( query, groupBy); List<TripProblemReportSummaryBean> beans = new ArrayList<TripProblemReportSummaryBean>( records.size()); for (T2<Object, Integer> record : records) { TripProblemReportSummaryBean bean = new TripProblemReportSummaryBean(); bean.setCount(record.getSecond()); switch (groupBy) { case TRIP: { AgencyAndId tripId = (AgencyAndId) record.getFirst(); bean.setTrip(_tripBeanService.getTripForId(tripId)); break; } case STATUS: { EProblemReportStatus status = (EProblemReportStatus) record.getFirst(); bean.setStatus(status); break; } case LABEL: { String label = (String) record.getFirst(); bean.setLabel(label); break; } } beans.add(bean); } return new ListBean<TripProblemReportSummaryBean>(beans, false); } public ListBean<StopProblemReportBean> getStopProblemReports( StopProblemReportQueryBean query) { List<StopProblemReportRecord> records = _userReportingDao.getStopProblemReports( query.getAgencyId(), query.getTimeFrom(), query.getTimeTo(), query.getStatus()); List<StopProblemReportBean> beans = new ArrayList<StopProblemReportBean>( records.size()); for (StopProblemReportRecord record : records) beans.add(getRecordAsBean(record)); return new ListBean<StopProblemReportBean>(beans, false); } public ListBean<TripProblemReportBean> getTripProblemReports( TripProblemReportQueryBean query) { List<TripProblemReportRecord> records = _userReportingDao.getTripProblemReports(query); List<TripProblemReportBean> beans = new ArrayList<TripProblemReportBean>( records.size()); for (TripProblemReportRecord record : records) beans.add(getRecordAsBean(record)); return new ListBean<TripProblemReportBean>(beans, false); } @Override public List<StopProblemReportBean> getAllStopProblemReportsForStopId( AgencyAndId stopId) { List<StopProblemReportRecord> records = _userReportingDao.getAllStopProblemReportsForStopId(stopId); List<StopProblemReportBean> beans = new ArrayList<StopProblemReportBean>( records.size()); for (StopProblemReportRecord record : records) beans.add(getRecordAsBean(record)); return beans; } @Override public List<TripProblemReportBean> getAllTripProblemReportsForTripId( AgencyAndId tripId) { List<TripProblemReportRecord> records = _userReportingDao.getAllTripProblemReportsForTripId(tripId); List<TripProblemReportBean> beans = new ArrayList<TripProblemReportBean>( records.size()); for (TripProblemReportRecord record : records) beans.add(getRecordAsBean(record)); return beans; } @Override public StopProblemReportBean getStopProblemReportForId(long id) { StopProblemReportRecord record = _userReportingDao.getStopProblemRecordForId(id); return getRecordAsBean(record); } @Override public TripProblemReportBean getTripProblemReportForId(long id) { TripProblemReportRecord record = _userReportingDao.getTripProblemRecordForId(id); return getRecordAsBean(record); } @Override public void deleteStopProblemReportForId(long id) { StopProblemReportRecord record = _userReportingDao.getStopProblemRecordForId(id); if (record != null) _userReportingDao.delete(record); } @Override public void updateTripProblemReport(TripProblemReportBean bean) { TripProblemReportRecord record = _userReportingDao.getTripProblemRecordForId(bean.getId()); if (record == null) return; record.setStatus(bean.getStatus()); record.setLabel(bean.getLabel()); _userReportingDao.saveOrUpdate(record); } @Override public void deleteTripProblemReportForId(long id) { TripProblemReportRecord record = _userReportingDao.getTripProblemRecordForId(id); if (record != null) _userReportingDao.delete(record); } @Override public List<String> getAllTripProblemReportLabels() { return _userReportingDao.getAllTripProblemReportLabels(); } @Override public void reportProblemWithPlannedTrip(TransitLocationBean from, TransitLocationBean to, long targetTime, ConstraintsBean constraints, PlannedTripProblemReportBean report) { } /**** * Private Methods ****/ private BlockInstance getBestBlockInstance( Collection<BlockInstance> blockInstances) { if (blockInstances.isEmpty()) return null; // Could we do something better here? return blockInstances.iterator().next(); } private BlockLocation getBestLocation(List<BlockLocation> blockLocations, TripProblemReportBean problem) { if (blockLocations.isEmpty()) return null; // Could we do something better here? return blockLocations.get(0); } private StopProblemReportBean getRecordAsBean(StopProblemReportRecord record) { AgencyAndId stopId = record.getStopId(); StopProblemReportBean bean = new StopProblemReportBean(); bean.setCode(record.getCode()); bean.setId(record.getId()); bean.setStatus(record.getStatus()); bean.setStopId(AgencyAndIdLibrary.convertToString(stopId)); bean.setTime(record.getTime()); bean.setUserComment(record.getUserComment()); if (record.getUserLat() != null) bean.setUserLat(record.getUserLat()); if (record.getUserLon() != null) bean.setUserLon(record.getUserLon()); if (record.getUserLocationAccuracy() != null) bean.setUserLocationAccuracy(record.getUserLocationAccuracy()); if (stopId != null) { try { bean.setStop(_stopBeanService.getStopForId(stopId)); } catch (NoSuchStopServiceException ex) { } } return bean; } private TripProblemReportBean getRecordAsBean(TripProblemReportRecord record) { AgencyAndId stopId = record.getStopId(); AgencyAndId tripId = record.getTripId(); TripProblemReportBean bean = new TripProblemReportBean(); bean.setCode(record.getCode()); bean.setId(record.getId()); bean.setServiceDate(record.getServiceDate()); bean.setStatus(record.getStatus()); bean.setLabel(record.getLabel()); bean.setStopId(AgencyAndIdLibrary.convertToString(stopId)); bean.setTime(record.getTime()); bean.setTripId(AgencyAndIdLibrary.convertToString(tripId)); bean.setUserComment(record.getUserComment()); bean.setUserLat(record.getUserLat()); bean.setUserLon(record.getUserLon()); bean.setUserLocationAccuracy(record.getUserLocationAccuracy()); bean.setUserOnVehicle(record.isUserOnVehicle()); bean.setUserVehicleNumber(record.getUserVehicleNumber()); bean.setPredicted(record.isPredicted()); bean.setVehicleId(AgencyAndIdLibrary.convertToString(record.getVehicleId())); bean.setDistanceAlongBlock(record.getDistanceAlongBlock()); bean.setScheduleDeviation(record.getScheduleDeviation()); bean.setVehicleLat(record.getVehicleLat()); bean.setVehicleLon(record.getVehicleLon()); if (stopId != null) { try { bean.setStop(_stopBeanService.getStopForId(stopId)); } catch (NoSuchStopServiceException ex) { } } if (tripId != null) { bean.setTrip(_tripBeanService.getTripForId(tripId)); } if (tripId != null && stopId != null) { TripEntry trip = _graph.getTripEntryForId(tripId); StopEntry stop = _graph.getStopEntryForId(stopId); if (trip != null && stop != null) { AgencyAndId vehicleId = record.getMatchedVehicleId(); if (vehicleId == null) vehicleId = record.getVehicleId(); ArrivalAndDepartureQuery query = new ArrivalAndDepartureQuery(); query.setStop(stop); query.setStopSequence(-1); query.setTrip(trip); query.setServiceDate(record.getServiceDate()); query.setVehicleId(vehicleId); query.setTime(record.getTime()); ArrivalAndDepartureInstance instance = _arrivalAndDepartureService.getArrivalAndDepartureForStop(query); if (instance != null) { StopTimeInstance sti = instance.getStopTimeInstance(); StopTimeInstanceBean stopTimeBean = _stopTimeBeanService.getStopTimeInstanceAsBean(sti); bean.setStopTime(stopTimeBean); } } } return bean; } }