package net.java.cargotracker.domain.model.cargo; import static org.junit.Assert.*; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import net.java.cargotracker.application.util.DateUtil; import net.java.cargotracker.domain.model.handling.HandlingEvent; import net.java.cargotracker.domain.model.handling.HandlingHistory; import net.java.cargotracker.domain.model.location.Location; import net.java.cargotracker.domain.model.location.SampleLocations; import net.java.cargotracker.domain.model.voyage.Voyage; import net.java.cargotracker.domain.model.voyage.VoyageNumber; import org.junit.Test; public class CargoTest { private final List<HandlingEvent> events = new ArrayList<>(); private final Voyage voyage = new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.STOCKHOLM) .addMovement(SampleLocations.HAMBURG, new Date(), new Date()) .addMovement(SampleLocations.HONGKONG, new Date(), new Date()) .addMovement(SampleLocations.MELBOURNE, new Date(), new Date()) .build(); @Test public void testConstruction() { TrackingId trackingId = new TrackingId("XYZ"); Date arrivalDeadline = DateUtil.toDate("2009-03-13"); RouteSpecification routeSpecification = new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, arrivalDeadline); Cargo cargo = new Cargo(trackingId, routeSpecification); assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery() .getRoutingStatus()); assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery() .getTransportStatus()); assertEquals(Location.UNKNOWN, cargo.getDelivery() .getLastKnownLocation()); assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); } @Test public void testRoutingStatus() { Cargo cargo = new Cargo(new TrackingId("XYZ"), new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); final Itinerary good = new Itinerary(); Itinerary bad = new Itinerary(); @SuppressWarnings("serial") RouteSpecification acceptOnlyGood = new RouteSpecification( cargo.getOrigin(), cargo.getRouteSpecification() .getDestination(), new Date()) { @Override public boolean isSatisfiedBy(Itinerary itinerary) { return itinerary == good; } }; cargo.specifyNewRoute(acceptOnlyGood); assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery() .getRoutingStatus()); cargo.assignToRoute(bad); assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery() .getRoutingStatus()); cargo.assignToRoute(good); assertEquals(RoutingStatus.ROUTED, cargo.getDelivery() .getRoutingStatus()); } @Test public void testLastKnownLocationUnknownWhenNoEvents() { Cargo cargo = new Cargo(new TrackingId("XYZ"), new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); assertEquals(Location.UNKNOWN, cargo.getDelivery() .getLastKnownLocation()); } @Test public void testLastKnownLocationReceived() throws Exception { Cargo cargo = populateCargoReceivedStockholm(); assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery() .getLastKnownLocation()); } @Test public void testLastKnownLocationClaimed() throws Exception { Cargo cargo = populateCargoClaimedMelbourne(); assertEquals(SampleLocations.MELBOURNE, cargo.getDelivery() .getLastKnownLocation()); } @Test public void testLastKnownLocationUnloaded() throws Exception { Cargo cargo = populateCargoOffHongKong(); assertEquals(SampleLocations.HONGKONG, cargo.getDelivery() .getLastKnownLocation()); } @Test public void testLastKnownLocationloaded() throws Exception { Cargo cargo = populateCargoOnHamburg(); assertEquals(SampleLocations.HAMBURG, cargo.getDelivery() .getLastKnownLocation()); } @Test public void testIsUnloadedAtFinalDestination() { Cargo cargo = setUpCargoWithItinerary(SampleLocations.HANGZOU, SampleLocations.TOKYO, SampleLocations.NEWYORK); assertFalse(cargo.getDelivery().isUnloadedAtDestination()); // Adding an event unrelated to unloading at final destination events.add(new HandlingEvent(cargo, new Date(10), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertFalse(cargo.getDelivery().isUnloadedAtDestination()); Voyage voyage = new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.HANGZOU).addMovement(SampleLocations.NEWYORK, new Date(), new Date()).build(); // Adding an unload event, but not at the final destination events.add(new HandlingEvent(cargo, new Date(20), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.TOKYO, voyage)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertFalse(cargo.getDelivery().isUnloadedAtDestination()); // Adding an event in the final destination, but not unload events.add(new HandlingEvent(cargo, new Date(30), new Date(), HandlingEvent.Type.CUSTOMS, SampleLocations.NEWYORK)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertFalse(cargo.getDelivery().isUnloadedAtDestination()); // Finally, cargo is unloaded at final destination events.add(new HandlingEvent(cargo, new Date(40), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.NEWYORK, voyage)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertTrue(cargo.getDelivery().isUnloadedAtDestination()); } // TODO: Generate test data some better way private Cargo populateCargoReceivedStockholm() throws Exception { Cargo cargo = new Cargo(new TrackingId("XYZ"), new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); HandlingEvent event = new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.STOCKHOLM); events.add(event); cargo.deriveDeliveryProgress(new HandlingHistory(events)); return cargo; } private Cargo populateCargoClaimedMelbourne() throws Exception { Cargo cargo = populateCargoOffMelbourne(); events.add(new HandlingEvent(cargo, getDate("2007-12-09"), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.MELBOURNE)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); return cargo; } private Cargo populateCargoOffHongKong() throws Exception { Cargo cargo = new Cargo(new TrackingId("XYZ"), new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.STOCKHOLM, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.HAMBURG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.HAMBURG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.HONGKONG, voyage)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); return cargo; } private Cargo populateCargoOnHamburg() throws Exception { Cargo cargo = new Cargo(new TrackingId("XYZ"), new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.STOCKHOLM, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.HAMBURG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.HAMBURG, voyage)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); return cargo; } private Cargo populateCargoOffMelbourne() throws Exception { Cargo cargo = new Cargo(new TrackingId("XYZ"), new RouteSpecification( SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.STOCKHOLM, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.HAMBURG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.HAMBURG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.HONGKONG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-05"), new Date(), HandlingEvent.Type.LOAD, SampleLocations.HONGKONG, voyage)); events.add(new HandlingEvent(cargo, getDate("2007-12-07"), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.MELBOURNE, voyage)); cargo.deriveDeliveryProgress(new HandlingHistory(events)); return cargo; } @Test public void testIsMisdirected() throws Exception { // A cargo with no itinerary is not misdirected Cargo cargo = new Cargo(new TrackingId("TRKID"), new RouteSpecification(SampleLocations.SHANGHAI, SampleLocations.GOTHENBURG, new Date())); assertFalse(cargo.getDelivery().isMisdirected()); cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); // A cargo with no handling events is not misdirected assertFalse(cargo.getDelivery().isMisdirected()); Collection<HandlingEvent> handlingEvents = new ArrayList<HandlingEvent>(); // Happy path handlingEvents.add(new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.RECEIVE, SampleLocations.SHANGHAI)); handlingEvents.add(new HandlingEvent(cargo, new Date(30), new Date(40), HandlingEvent.Type.LOAD, SampleLocations.SHANGHAI, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(50), new Date(60), HandlingEvent.Type.UNLOAD, SampleLocations.ROTTERDAM, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(70), new Date(80), HandlingEvent.Type.LOAD, SampleLocations.ROTTERDAM, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(90), new Date(100), HandlingEvent.Type.UNLOAD, SampleLocations.GOTHENBURG, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(110), new Date(120), HandlingEvent.Type.CLAIM, SampleLocations.GOTHENBURG)); handlingEvents.add(new HandlingEvent(cargo, new Date(130), new Date(140), HandlingEvent.Type.CUSTOMS, SampleLocations.GOTHENBURG)); events.addAll(handlingEvents); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertFalse(cargo.getDelivery().isMisdirected()); // Try a couple of failing ones cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); handlingEvents = new ArrayList<HandlingEvent>(); handlingEvents.add(new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU)); events.addAll(handlingEvents); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertTrue(cargo.getDelivery().isMisdirected()); cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); handlingEvents = new ArrayList<HandlingEvent>(); handlingEvents.add(new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.RECEIVE, SampleLocations.SHANGHAI)); handlingEvents.add(new HandlingEvent(cargo, new Date(30), new Date(40), HandlingEvent.Type.LOAD, SampleLocations.SHANGHAI, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(50), new Date(60), HandlingEvent.Type.UNLOAD, SampleLocations.ROTTERDAM, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(70), new Date(80), HandlingEvent.Type.LOAD, SampleLocations.ROTTERDAM, voyage)); events.addAll(handlingEvents); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertTrue(cargo.getDelivery().isMisdirected()); cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); handlingEvents = new ArrayList<HandlingEvent>(); handlingEvents.add(new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.RECEIVE, SampleLocations.SHANGHAI)); handlingEvents.add(new HandlingEvent(cargo, new Date(30), new Date(40), HandlingEvent.Type.LOAD, SampleLocations.SHANGHAI, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(50), new Date(60), HandlingEvent.Type.UNLOAD, SampleLocations.ROTTERDAM, voyage)); handlingEvents.add(new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.ROTTERDAM)); events.addAll(handlingEvents); cargo.deriveDeliveryProgress(new HandlingHistory(events)); assertTrue(cargo.getDelivery().isMisdirected()); } private Cargo setUpCargoWithItinerary(Location origin, Location midpoint, Location destination) { Cargo cargo = new Cargo(new TrackingId("CARGO1"), new RouteSpecification(origin, destination, new Date())); Itinerary itinerary = new Itinerary(Arrays.asList(new Leg(voyage, origin, midpoint, new Date(), new Date()), new Leg(voyage, midpoint, destination, new Date(), new Date()))); cargo.assignToRoute(itinerary); return cargo; } /** * Parse an ISO 8601 (YYYY-MM-DD) String to Date * * @param isoFormat * String to parse. * @return Created date instance. * @throws ParseException * Thrown if parsing fails. */ private Date getDate(String isoFormat) throws ParseException { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); return dateFormat.parse(isoFormat); } }