ExternalRoutingService.java 3.5KB

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