View Javadoc

1   package se.citerus.dddsample.infrastructure.routing;
2   
3   import com.pathfinder.api.GraphTraversalService;
4   import com.pathfinder.api.TransitEdge;
5   import com.pathfinder.api.TransitPath;
6   import org.apache.commons.logging.Log;
7   import org.apache.commons.logging.LogFactory;
8   import se.citerus.dddsample.domain.model.cargo.Itinerary;
9   import se.citerus.dddsample.domain.model.cargo.Leg;
10  import se.citerus.dddsample.domain.model.cargo.RouteSpecification;
11  import se.citerus.dddsample.domain.model.location.Location;
12  import se.citerus.dddsample.domain.model.location.LocationRepository;
13  import se.citerus.dddsample.domain.model.location.UnLocode;
14  import se.citerus.dddsample.domain.model.voyage.VoyageNumber;
15  import se.citerus.dddsample.domain.model.voyage.VoyageRepository;
16  import se.citerus.dddsample.domain.service.RoutingService;
17  
18  import java.rmi.RemoteException;
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.Properties;
23  
24  /**
25   * Our end of the routing service. This is basically a data model
26   * translation layer between our domain model and the API put forward
27   * by the routing team, which operates in a different context from us.
28   *
29   */
30  public class ExternalRoutingService implements RoutingService {
31  
32    private GraphTraversalService graphTraversalService;
33    private LocationRepository locationRepository;
34    private VoyageRepository voyageRepository;
35    private static final Log log = LogFactory.getLog(ExternalRoutingService.class);
36  
37    public List<Itinerary> fetchRoutesForSpecification(RouteSpecification routeSpecification) {
38      /*
39        The RouteSpecification is picked apart and adapted to the external API.
40       */
41      final Location origin = routeSpecification.origin();
42      final Location destination = routeSpecification.destination();
43  
44      final Properties limitations = new Properties();
45      limitations.setProperty("DEADLINE", routeSpecification.arrivalDeadline().toString());
46  
47      final List<TransitPath> transitPaths;
48      try {
49        transitPaths = graphTraversalService.findShortestPath(
50        origin.unLocode().idString(),
51        destination.unLocode().idString(),
52        limitations
53      );
54      } catch (RemoteException e) {
55        log.error(e, e);
56        return Collections.EMPTY_LIST;
57      }
58  
59      /*
60       The returned result is then translated back into our domain model.
61      */
62      final List<Itinerary> itineraries = new ArrayList<Itinerary>();
63  
64      for (TransitPath transitPath : transitPaths) {
65        final Itinerary itinerary = toItinerary(transitPath);
66        // Use the specification to safe-guard against invalid itineraries
67        if (routeSpecification.isSatisfiedBy(itinerary)) {
68          itineraries.add(itinerary);
69        } else {
70          log.warn("Received itinerary that did not satisfy the route specification");
71        }
72      }
73  
74      return itineraries;
75    }
76  
77    private Itinerary toItinerary(TransitPath transitPath) {
78      List<Leg> legs = new ArrayList<Leg>(transitPath.getTransitEdges().size());
79      for (TransitEdge edge : transitPath.getTransitEdges()) {
80        legs.add(toLeg(edge));
81      }
82      return new Itinerary(legs);
83    }
84  
85    private Leg toLeg(TransitEdge edge) {
86      return new Leg(
87        voyageRepository.find(new VoyageNumber(edge.getVoyageNumber())),
88        locationRepository.find(new UnLocode(edge.getFromUnLocode())),
89        locationRepository.find(new UnLocode(edge.getToUnLocode())),
90        edge.getFromDate(), edge.getToDate()
91      );
92    }
93  
94    public void setGraphTraversalService(GraphTraversalService graphTraversalService) {
95      this.graphTraversalService = graphTraversalService;
96    }
97  
98    public void setLocationRepository(LocationRepository locationRepository) {
99      this.locationRepository = locationRepository;
100   }
101 
102   public void setVoyageRepository(VoyageRepository voyageRepository) {
103     this.voyageRepository = voyageRepository;
104   }
105   
106 }