View Javadoc

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      // TODO modeling this as a cargo factory might be suitable
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  }