ParkingLotService.java 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package eu.fcheret.parkingtoll.service;
  2. import eu.fcheret.parkingtoll.exceptions.NoSuchCarInParkingException;
  3. import eu.fcheret.parkingtoll.exceptions.ParkingIsFullException;
  4. import eu.fcheret.parkingtoll.exceptions.ParkingNotFoundException;
  5. import eu.fcheret.parkingtoll.exceptions.ParkingTypeDoesNotExistException;
  6. import eu.fcheret.parkingtoll.model.CarSlot;
  7. import eu.fcheret.parkingtoll.model.Layout;
  8. import eu.fcheret.parkingtoll.model.ParkingLot;
  9. import eu.fcheret.parkingtoll.persistence.Dao;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.stereotype.Service;
  12. import java.math.BigDecimal;
  13. import java.time.Instant;
  14. import java.util.ArrayList;
  15. import java.util.Collection;
  16. import java.util.stream.Collectors;
  17. @Service
  18. public class ParkingLotService {
  19. private Dao<ParkingLot> persistenceManager;
  20. @Autowired
  21. public ParkingLotService(Dao<ParkingLot> persistenceManager) {
  22. this.persistenceManager = persistenceManager;
  23. }
  24. public ParkingLot createParkingLot(ParkingLot parkingLotItem) {
  25. return persistenceManager.save(parkingLotItem);
  26. }
  27. public ParkingLot deleteParkingLotById(Long parkingLotId) {
  28. //check if object exists
  29. ParkingLot parkingLot = findParkingLotByIdOrThrow(parkingLotId);
  30. persistenceManager.delete(parkingLotId);
  31. return parkingLot;
  32. }
  33. public ParkingLot getParkingById(Long parkingLotId) {
  34. ParkingLot parkingLot = persistenceManager.findById(parkingLotId);
  35. if(parkingLot == null){
  36. throw new ParkingNotFoundException("The given ID is not associated with a parking lot.");
  37. }
  38. return parkingLot;
  39. }
  40. public CarSlot leaveParkingLot(Long parkingLotId, CarSlot carSlotItem) {
  41. ParkingLot parkingLot = findParkingLotByIdOrThrow(parkingLotId);
  42. Layout layout = getLayoutByNameOrThrow(carSlotItem.getType(),parkingLot);
  43. CarSlot carSlot;
  44. synchronized (this) {
  45. carSlot = findCarSlotByIdOrThrow(carSlotItem.getSlot(), layout);
  46. carSlot.setDepartureTime(Instant.now());
  47. layout.incrementAndFree(carSlot.getSlot());
  48. }
  49. BigDecimal fare = parkingLot.getFareProcessor().computeFare(carSlot);
  50. carSlot.setPrice(fare);
  51. return carSlot;
  52. }
  53. public CarSlot parkAtParkingLot(Long parkingLotId, CarSlot carSlotItem) {
  54. //check if the asked parking exists
  55. ParkingLot parkingLot = findParkingLotByIdOrThrow(parkingLotId);
  56. //check if there is available slots
  57. Layout layout = getLayoutByNameOrThrow(carSlotItem.getType(), parkingLot);
  58. isAvailableOrThrow(layout);
  59. //found & available spot
  60. synchronized (this){
  61. //double check locking
  62. parkingLot = findParkingLotByIdOrThrow(parkingLotId);
  63. layout = getLayoutByNameOrThrow(carSlotItem.getType(), parkingLot);
  64. isAvailableOrThrow(layout);
  65. Long slotId = layout.decrementAndGetID();
  66. carSlotItem.setSlot(slotId);
  67. carSlotItem.setParkingLotId(parkingLotId);
  68. carSlotItem.setArrivalTime(Instant.now());
  69. layout.getCarSlots().put(slotId, carSlotItem);
  70. persistenceManager.save(parkingLot);
  71. }
  72. return carSlotItem;
  73. }
  74. private void isAvailableOrThrow(Layout layout){
  75. if(layout.getAvailable().get() == 0){
  76. throw new ParkingIsFullException("Parking lot is full for this type of car");
  77. }
  78. }
  79. public ParkingLot updateParkingLot(Long parkingLotId, ParkingLot parkingLotItem) {
  80. //parking lot exists ?
  81. ParkingLot parkingLot = persistenceManager.findById(parkingLotId);
  82. ParkingLot newParkingLot = null;
  83. if(parkingLot == null){
  84. //new one, save it
  85. newParkingLot = persistenceManager.save(parkingLotItem);
  86. } else {
  87. persistenceManager.update(parkingLotId, parkingLotItem);
  88. }
  89. return newParkingLot;
  90. }
  91. public Collection<ParkingLot> searchParkingLot(String searchString) {
  92. if(searchString == null || searchString.trim().isEmpty()){
  93. return persistenceManager.getAll();
  94. }
  95. return persistenceManager.getAll().stream().
  96. filter(parkingLot -> parkingLot.getName().trim().toUpperCase().contains(searchString.trim().toUpperCase()))
  97. .collect(Collectors.toCollection(ArrayList::new));
  98. }
  99. private Layout getLayoutByNameOrThrow(String slotName, ParkingLot parkingLot){
  100. return parkingLot.getLayoutList().stream()
  101. .filter(lay -> lay.getName().equals(slotName)).findFirst()
  102. .orElseThrow(() -> new ParkingTypeDoesNotExistException("This type of slot does not exist in this parking lot"));
  103. }
  104. private ParkingLot findParkingLotByIdOrThrow(Long id){
  105. ParkingLot parkingLot = persistenceManager.findById(id);
  106. if(parkingLot == null){
  107. throw new ParkingNotFoundException("The given ID is not associated with a parking lot.");
  108. }
  109. return parkingLot;
  110. }
  111. private CarSlot findCarSlotByIdOrThrow(Long id, Layout layout){
  112. CarSlot carSlot = layout.getCarSlots().get(id);
  113. if(carSlot == null){
  114. throw new NoSuchCarInParkingException("This car is not at the specified location");
  115. }
  116. return carSlot;
  117. }
  118. }