/**
* @author Alfort Robert - Kleindl Stefan
* ServiceLayer - Trips
* @version 1.1
*/
package at.fhj.itm.business;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.primefaces.json.JSONException;
import org.primefaces.json.JSONObject;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;
import org.primefaces.model.map.Polyline;
import at.fhj.itm.dao.DAOException;
import at.fhj.itm.dao.PointDAO;
import at.fhj.itm.dao.TripDAO;
import at.fhj.itm.dao.WaypointDAO;
import at.fhj.itm.model.Location;
import at.fhj.itm.model.Point;
import at.fhj.itm.model.Trip;
import at.fhj.itm.model.User;
import at.fhj.itm.model.Waypoint;
import at.fhj.itm.util.GoogleUtil;
import at.fhj.itm.util.JsfUtil;
import at.fhj.itm.util.Validator;
import com.sun.servicetag.UnauthorizedAccessException;
public class ServiceTripImpl extends ServiceAbstract implements ServiceTrip {
private final Logger logger = Logger.getLogger(ServiceAbstract.class);
private JsfUtil jsfUtil;
private GoogleUtil googleUtil;
private TripDAO tripDAO;
/**
* This Methode sets required DAO's
*
* @param tripDAO
* @param waypointDAO
* @param pointDAO
* @param dataSrc
*/
public ServiceTripImpl(TripDAO tripDAO, WaypointDAO waypointDAO,
PointDAO pointDAO, DataSource dataSrc, JsfUtil jsfUtil,
GoogleUtil googleUtil) {
super(dataSrc);
this.jsfUtil = jsfUtil;
this.googleUtil = googleUtil;
setTripDAO(tripDAO);
setWaypointDAO(waypointDAO);
setPointDAO(pointDAO);
}
/**
* Returns the TripDAO currently used by this service
*
* @return
*/
public final TripDAO getTripDAO() {
return tripDAO;
}
/**
* Sets a new Trip DAO for the dao
* <p>
* This method should only be used for testing purposes
* </p>
*
* @param tripDAO
* the TripDAO which sould be set.
*/
public final void setTripDAO(final TripDAO tripDAO) {
Validator.validateNotNull(tripDAO, "tripDAO");
this.tripDAO = tripDAO;
}
private WaypointDAO waypointDAO;
/**
* returns the Waypoint DAO used by the service
*
* @return
*/
public final WaypointDAO getWaypointDAO() {
return waypointDAO;
}
private PointDAO pointDAO;
/**
* Returns the PointDAO used by this service
*
* @return
*/
public final PointDAO getPointDAO() {
return pointDAO;
}
/**
* Sets a new PointDAO which is to be used in this service.
* <p>
* This method should only be used for testing purposes
* </p>
*
* @param pointDAO
* the point DAO which should be set
*/
public final void setPointDAO(PointDAO pointDAO) {
Validator.validateNotNull(pointDAO, "pointDAO");
this.pointDAO = pointDAO;
}
/**
* Sets a new waypoint DAO for this service
* <p>
* This method should only be used for testing purposes
* </p>
*
* @param waypointDAO
*/
public final void setWaypointDAO(final WaypointDAO waypointDAO) {
Validator.validateNotNull(tripDAO, "waypointDAO");
this.waypointDAO = waypointDAO;
}
/**
* searchTrip goes through all stored trips and triggers a trip containing
* from or to. If there is a successfull match the trip is stored in
* matchingTrips.
*
* @param from
* city in which the desired trip should start
* @param to
* target city of the desired trip
*/
@Override
public List<Trip> searchTrip(String from, String to) {
List<Trip> matchingTrips = new ArrayList<Trip>();
try {
begin();
for (Trip trip : tripDAO.selectAll(getConnection())) {
if (trip.getWaypoint().getFromLocation().getCity()
.equalsIgnoreCase(from)
|| trip.getWaypoint().getToLocation().getCity()
.equalsIgnoreCase(to))
matchingTrips.add(trip);
}
commit();
closeConnection();
} catch (Exception ex) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving trips");
} finally {
closeConnection();
}
return Collections.unmodifiableList(matchingTrips);
}
/**
* searchTrip goes through all stored trips and triggers a trip containing
* from or to. If there is a successfull match the trip is stored in
* matchingTrips.
*
* @param from
* city in which the desired trip should start
* @param to
* target city of the desired trip
* @param driver
* filters for desired driver
*/
@Override
public List<Trip> searchTrip(String from, String to, String driver) {
List<Trip> matchingTrips = new ArrayList<Trip>();
try {
begin();
for (Trip trip : tripDAO.selectAll(getConnection())) {
if ((trip.getWaypoint().getFromLocation().getCity()
.equalsIgnoreCase(from) || trip.getWaypoint()
.getToLocation().getCity().equalsIgnoreCase(to))
&& trip.getUser().getUsername()
.equalsIgnoreCase(driver))
matchingTrips.add(trip);
}
commit();
closeConnection();
} catch (Exception ex) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving trips");
} finally {
closeConnection();
}
return Collections.unmodifiableList(matchingTrips);
}
/**
* is either updating or inserting a new trip to db.
*
* @param departure
* @param seats
* @param fromLocation
* @param toLocation
* @throws ServiceException
*
*/
@Override
public void insertTrip(Date departure, int seats, Location fromLocation,
Location toLocation, Location... stops) throws ServiceException {
User user = jsfUtil.getLoggedInUser();
if (user == null)
throw new UnauthorizedAccessException("No user logged in!");
Trip newTrip;
try {
begin();
List<Waypoint> stopovers = null;
if (stops.length > 0) {
stopovers = new ArrayList<Waypoint>();
for (Location l : stops) {
stopovers.add(new Waypoint(fromLocation, l, user, null,
true));
stopovers
.add(new Waypoint(l, toLocation, user, null, true));
}
}
Waypoint waypoint = new Waypoint(fromLocation, toLocation, user,
null, true);
newTrip = new Trip(user, departure, seats, waypoint, "");
// insert the trip to DAO
getTripDAO().update(newTrip, getConnection());
if (stopovers != null) {
for (Waypoint wp : stopovers) {
getWaypointDAO().update(wp, getConnection());
getWaypointDAO().addWaypointToTrip(newTrip, wp,
getConnection());
}
}
commit();
} catch (DAOException e) {
tryRollbackAndLogFailure();
throw new ServiceException("Can't insert trip!", e);
} catch (SQLException e) {
tryRollbackAndLogFailure();
throw new ServiceException("Can't insert trip!", e);
} finally {
closeConnection();
}
this.loadAndPersistGoogleData(newTrip);
}
/**
* Removing a trip with a given id
*
* @params idString
*/
@Override
public void removeTrip(final String idString) {
logger.debug("removeTrip()");
Validator.validateNotNull(idString, "id [String]");
try {
int id = Integer.valueOf(idString);
begin();
getTripDAO().delete(getTripDAO().getByID(id, getConnection()),
getConnection());
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Can't remove Trip!", e);
} finally {
closeConnection();
}
}
/**
* Removing a waypoint with a given id
*
* @params idString
*/
@Override
public void removeWaypoint(final String idString) {
logger.debug("removeWaypoint()");
Validator.validateNotNull(idString, "id [String]");
try {
int id = Integer.valueOf(idString);
begin();
getWaypointDAO().delete(
getWaypointDAO().getByID(id, getConnection()),
getConnection());
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Can't remove Waypoint!", e);
} finally {
closeConnection();
}
}
/**
* getWaypointsForUser retrives all waypoints from a given User
*
* @params user
*/
@Override
public List<Waypoint> getWaypointsForUser(User u) {
List<Waypoint> wp = null;
try {
begin();
wp = waypointDAO.getWaypointsFromUser(u, getConnection());
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving waypoints for user", e);
} finally {
closeConnection();
}
return wp;
}
/**
* getPointsForTrip retrives all Points of a trip
*
* @params trip
*/
@Override
public List<Point> getPointsForTrip(Trip t) {
List<Point> points = null;
try {
begin();
points = getPointDAO().getByTrip(t, getConnection());
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving waypoints for points",
e);
} finally {
closeConnection();
}
return points;
}
/**
* getWaypointsForTrip returns all waypoints of a given trip
*
* @params trip
*/
@Override
public List<Waypoint> getWaypointsForTrip(Trip trip) {
List<Waypoint> wp = null;
try {
begin();
wp = waypointDAO.getWaypointsForTrip(trip, getConnection());
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving waypoints for trip", e);
} finally {
closeConnection();
}
return wp;
}
/**
* selectAllTrips return all stored trips.
*/
@Override
public List<Trip> selectAllTrips() {
List<Trip> trips = null;
try {
begin();
trips = getTripDAO().selectAll(getConnection());
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving trips from database",
e);
} finally {
closeConnection();
}
return trips;
}
/**
* bookWaypointForTrip is adding a given waypoint to a given trip.
*
* @params wp
* @params trip
*/
@Override
public void bookWaypointForTrip(Waypoint wp, Trip trip) {
try {
begin();
getWaypointDAO().update(wp, getConnection());
getWaypointDAO().addWaypointToTrip(trip, wp, connection);
commit();
} catch (Exception e) {
tryRollbackAndLogFailure();
throw new ServiceException("Error while booking waypoint to a trip");
} finally {
closeConnection();
}
}
/**
* {@link ServiceTrip#getArivalTime(Trip)}
*/
@Override
public Date getArivalTime(Trip t) {
try {
long arrivalTime = t.getDeparture().getTime();
List<Point> pointList = getPointsForTrip(t);
if (pointList.isEmpty()) {
pointList = this.loadAndPersistGoogleData(t);
}
for (Point p : pointList)
arrivalTime += p.getDuration() * 1000;
return new Date(arrivalTime);
} catch (Exception ex) {
throw new ServiceException("Error while calculating arival time.",
ex);
}
}
@Override
public MapModel getMapModelFromTrip(Trip trip) throws ServiceException {
MapModel mapModel = new DefaultMapModel();
List<Point> pointList = getPointsForTrip(trip);
if (pointList.isEmpty()) {
pointList = this.loadAndPersistGoogleData(trip);
}
Polyline polyline = new Polyline();
polyline.getPaths().addAll(pointList);
Marker beginMarker = new Marker(pointList.get(0), trip.getWaypoint()
.getFromLocation().getCity());
Marker endMarker = new Marker(pointList.get(pointList.size() - 1), trip
.getWaypoint().getToLocation().getCity());
polyline.setStrokeWeight(10);
polyline.setStrokeColor("#FF9900");
polyline.setStrokeOpacity(0.7);
mapModel.addOverlay(beginMarker);
mapModel.addOverlay(polyline);
mapModel.addOverlay(endMarker);
return mapModel;
}
@Override
public List<Trip> allBookedTripsByUser(int userId) {
List<Trip> bookedTrips = new ArrayList<Trip>();
try {
begin();
bookedTrips = tripDAO.allBookedTripsByUser(userId, getConnection());
commit();
closeConnection();
} catch (Exception ex) {
tryRollbackAndLogFailure();
throw new ServiceException("Error retrieving trips");
} finally {
closeConnection();
}
return Collections.unmodifiableList(bookedTrips);
}
/**
* Helper method to update a list of trip points and returns all points of a
* trip collected in a List. It is using a own transaction. Will log any
* error.
*
* @param newTrip
* whose points should be updated
* @return a list of updated trip poins.
*/
private List<Point> loadAndPersistGoogleData(Trip newTrip) {
try {
begin();
List<Waypoint> stops = new ArrayList<Waypoint>();
stops.addAll(waypointDAO.getWaypointsForTrip(newTrip,
getConnection()));
for (int i = stops.size() - 1; i >= 0; i--)
if (!stops.get(i).getUser().equals(newTrip.getUser()))
stops.remove(i); // use only drivers assignet waypoints
JSONObject jsonObject = googleUtil.getJsonObj(newTrip, stops);
newTrip = googleUtil.loadGoogleData(newTrip, jsonObject);
getPointDAO().insertPoints(newTrip.getPoints(), getConnection());
commit();
} catch (JSONException je) {
logger.error("JSONException: failed to load mapdata: " + newTrip);
} catch (IOException e) {
logger.error("IOException: failed to load mapdata: " + newTrip);
} catch (DAOException e) {
tryRollbackAndLogFailure();
logger.error("DAOException: failed to load waypoints/persist mapdata: "
+ newTrip);
} catch (SQLException e) {
tryRollbackAndLogFailure();
logger.error("SQLException: failed to load waypoints/persist mapdata: "
+ newTrip);
} finally {
closeConnection();
}
return newTrip.getPoints();
}
}