1 package se.citerus.dddsample.application.impl;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.springframework.transaction.annotation.Transactional;
6 import se.citerus.dddsample.application.BookingService;
7 import se.citerus.dddsample.domain.model.cargo.*;
8 import se.citerus.dddsample.domain.model.location.Location;
9 import se.citerus.dddsample.domain.model.location.LocationRepository;
10 import se.citerus.dddsample.domain.model.location.UnLocode;
11 import se.citerus.dddsample.domain.service.RoutingService;
12
13 import java.util.Collections;
14 import java.util.Date;
15 import java.util.List;
16
17 public final class BookingServiceImpl implements BookingService {
18
19 private final CargoRepository cargoRepository;
20 private final LocationRepository locationRepository;
21 private final RoutingService routingService;
22 private final Log logger = LogFactory.getLog(getClass());
23
24 public BookingServiceImpl(final CargoRepository cargoRepository,
25 final LocationRepository locationRepository,
26 final RoutingService routingService) {
27 this.cargoRepository = cargoRepository;
28 this.locationRepository = locationRepository;
29 this.routingService = routingService;
30 }
31
32 @Override
33 @Transactional
34 public TrackingId bookNewCargo(final UnLocode originUnLocode,
35 final UnLocode destinationUnLocode,
36 final Date arrivalDeadline) {
37
38 final TrackingId trackingId = cargoRepository.nextTrackingId();
39 final Location origin = locationRepository.find(originUnLocode);
40 final Location destination = locationRepository.find(destinationUnLocode);
41 final RouteSpecification routeSpecification = new RouteSpecification(origin, destination, arrivalDeadline);
42
43 final Cargo cargo = new Cargo(trackingId, routeSpecification);
44
45 cargoRepository.store(cargo);
46 logger.info("Booked new cargo with tracking id " + cargo.trackingId().idString());
47
48 return cargo.trackingId();
49 }
50
51 @Override
52 @Transactional
53 public List<Itinerary> requestPossibleRoutesForCargo(final TrackingId trackingId) {
54 final Cargo cargo = cargoRepository.find(trackingId);
55
56 if (cargo == null) {
57 return Collections.emptyList();
58 }
59
60 return routingService.fetchRoutesForSpecification(cargo.routeSpecification());
61 }
62
63 @Override
64 @Transactional
65 public void assignCargoToRoute(final Itinerary itinerary, final TrackingId trackingId) {
66 final Cargo cargo = cargoRepository.find(trackingId);
67 if (cargo == null) {
68 throw new IllegalArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
69 }
70
71 cargo.assignToRoute(itinerary);
72 cargoRepository.store(cargo);
73
74 logger.info("Assigned cargo " + trackingId + " to new route");
75 }
76
77 @Override
78 @Transactional
79 public void changeDestination(final TrackingId trackingId, final UnLocode unLocode) {
80 final Cargo cargo = cargoRepository.find(trackingId);
81 final Location newDestination = locationRepository.find(unLocode);
82
83 final RouteSpecification routeSpecification = new RouteSpecification(
84 cargo.origin(), newDestination, cargo.routeSpecification().arrivalDeadline()
85 );
86 cargo.specifyNewRoute(routeSpecification);
87
88 cargoRepository.store(cargo);
89 logger.info("Changed destination for cargo " + trackingId + " to " + routeSpecification.destination());
90 }
91
92 }