package pizza.service; import pizza.dao.DbDAO; import pizza.dao.AdminDAO; import pizza.dao.PizzaOrderDAO; import pizza.domain.PizzaOrder; import pizza.domain.Topping; import java.lang.Exception; import java.util.List; // This class captures the business logic for the administration related interactions. // It receives references to the singleton DAO objects, // at creation time. Since these DAO objects are pure API, // (no state except for one field valid only during initDB) so is this one. // So it can be called a stateless service API. // Alternatively, new DAO objects could be created for each transaction // as in the EDM implementation, but here they would always be the same API objects. // Note all the similar code for each service call. This can be eliminated by // using interception of these calls using AOP. // Note that each call catches DAO/Hibernate exceptions and throws its own // exception, after rolling back the transaction. The new exception, with // a useful message, then gets caught in the presentation layer. public class AdminService { private DbDAO dbDAO; private AdminDAO adminDAO; private PizzaOrderDAO pizzaOrderDAO; public AdminService(DbDAO db, AdminDAO admDAO, PizzaOrderDAO poDAO) { dbDAO = db; adminDAO = admDAO; pizzaOrderDAO = poDAO; } public void initializeDb() throws ServiceException { try { dbDAO.startTransaction(); dbDAO.initializeDb(); dbDAO.commitTransaction(); } catch (Exception e) { // the following doesn't itself throw, but it handles the case that // rollback throws, discarding that exception object dbDAO.rollbackAfterException(); throw new ServiceException("Can't initialize DB: ", e); } } public void addTopping(String name) throws ServiceException { try { dbDAO.startTransaction(); adminDAO.createTopping(name); dbDAO.commitTransaction(); } catch (Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Topping was not added successfully: ", e); } } public void markNextOrderReady() throws ServiceException { try { dbDAO.startTransaction(); int ordNo = pizzaOrderDAO.findFirstOrder(PizzaOrder.PREPARING); pizzaOrderDAO.updateOrderStatus(ordNo, PizzaOrder.BAKED); dbDAO.commitTransaction(); } catch (Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Error in marking the next order ready", e); } } public void advanceDay() throws ServiceException { try { dbDAO.startTransaction(); List pizzaOrders = getTodaysOrders(); // day is done, so mark today's pizzas as "finished" for (PizzaOrder order: pizzaOrders) { pizzaOrderDAO.updateOrderStatus(order.getId(), PizzaOrder.FINISHED); } adminDAO.advanceDay(); dbDAO.commitTransaction(); } catch (Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Unsuccessful advance day", e); } } public void addPizzaSize(String name) throws ServiceException { try { dbDAO.startTransaction(); adminDAO.createPizzaSize(name); dbDAO.commitTransaction(); } catch (Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Pizza size was not added successfully", e); } } public void deleteTopping(int toppingId) throws ServiceException { try { dbDAO.startTransaction(); adminDAO.deleteTopping(toppingId); dbDAO.commitTransaction(); }catch(Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Error while removing topping ", e); } } public List getDailyReport() throws ServiceException { try { dbDAO.startTransaction(); List orders = getTodaysOrders(); // materialize details during tx for (PizzaOrder o: orders) { o.getPizzaSize().getSizeName(); for (Topping t: o.getToppings()) t.getToppingName(); } dbDAO.commitTransaction(); return orders; } catch (Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Error while getting daily report ", e); } } // helper method to getDailyReport and advanceDay // executes inside the current transaction private List getTodaysOrders() throws Exception { int today = adminDAO.findCurrentDay(); List orders = pizzaOrderDAO.findOrdersByDays(today, today); return orders; } public void deletePizzaSize(int sizeId) throws ServiceException { try { dbDAO.startTransaction(); adminDAO.deletePizzaSize(sizeId); dbDAO.commitTransaction(); }catch(Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Error while removing topping", e); } } public List getAdminReport() throws ServiceException { List report; try { dbDAO.startTransaction(); int prevLastReportDay = adminDAO.findLastReportDay(); int today = adminDAO.findCurrentDay(); report = pizzaOrderDAO.findOrdersByDays(prevLastReportDay+1, today); // materialize details during tx for (PizzaOrder o: report) { o.getPizzaSize().getSizeName(); for (Topping t: o.getToppings()) t.getToppingName(); } if (today > prevLastReportDay) { adminDAO.updateLastReportDate(today); // advamce past reported days } dbDAO.commitTransaction(); } catch(Exception e){ dbDAO.rollbackAfterException(); throw new ServiceException("Error in admin report", e); } return report; } public int getCurrentDay() throws ServiceException { int day; try { dbDAO.startTransaction(); // read-only day = adminDAO.findCurrentDay(); dbDAO.commitTransaction(); } catch(Exception e) { dbDAO.rollbackAfterException(); throw new ServiceException("Can't access date in db: ", e); } return day; } }