package org.sculptor.dddsample.cargo.domain;
import static org.sculptor.dddsample.cargo.domain.TrackingId.trackingId;
import static org.sculptor.dddsample.location.domain.SampleLocations.GOTHENBURG;
import static org.sculptor.dddsample.location.domain.SampleLocations.HAMBURG;
import static org.sculptor.dddsample.location.domain.SampleLocations.HANGZOU;
import static org.sculptor.dddsample.location.domain.SampleLocations.HONGKONG;
import static org.sculptor.dddsample.location.domain.SampleLocations.MELBOURNE;
import static org.sculptor.dddsample.location.domain.SampleLocations.NEWYORK;
import static org.sculptor.dddsample.location.domain.SampleLocations.ROTTERDAM;
import static org.sculptor.dddsample.location.domain.SampleLocations.SHANGHAI;
import static org.sculptor.dddsample.location.domain.SampleLocations.STOCKHOLM;
import static org.sculptor.dddsample.location.domain.SampleLocations.TOKYO;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.sculptor.dddsample.carrier.domain.CarrierMovement;
import org.sculptor.dddsample.carrier.domain.CarrierMovementId;
import org.sculptor.dddsample.location.domain.Location;
public class CargoTest extends TestCase {
private Set<HandlingEvent> events;
public void testlastKnownLocationUnknownWhenNoEvents() throws Exception {
Cargo cargo = new Cargo(trackingId("XYZ"), STOCKHOLM, MELBOURNE);
assertEquals(Location.UNKNOWN, cargo.lastKnownLocation());
}
public void testlastKnownLocationReceived() throws Exception {
Cargo cargo = populateCargoReceivedStockholm();
assertEquals(STOCKHOLM, cargo.lastKnownLocation());
}
public void testlastKnownLocationClaimed() throws Exception {
Cargo cargo = populateCargoClaimedMelbourne();
assertEquals(MELBOURNE, cargo.lastKnownLocation());
}
public void testlastKnownLocationUnloaded() throws Exception {
Cargo cargo = populateCargoOffHongKong();
assertEquals(HONGKONG, cargo.lastKnownLocation());
}
public void testlastKnownLocationloaded() throws Exception {
Cargo cargo = populateCargoOnHamburg();
assertEquals(HAMBURG, cargo.lastKnownLocation());
}
public void testAtFinalLocation() throws Exception {
Cargo cargo = populateCargoOffMelbourne();
assertTrue(cargo.hasArrived());
}
public void testNotAtFinalLocationWhenNotUnloaded() throws Exception {
Cargo cargo = populateCargoOnHongKong();
assertFalse(cargo.hasArrived());
}
public void testEquality() throws Exception {
Cargo c1 = new Cargo(trackingId("ABC"), STOCKHOLM, HONGKONG);
Cargo c2 = new Cargo(trackingId("CBA"), STOCKHOLM, HONGKONG);
Cargo c3 = new Cargo(trackingId("ABC"), STOCKHOLM, MELBOURNE);
Cargo c4 = new Cargo(trackingId("ABC"), STOCKHOLM, HONGKONG);
assertTrue("Cargos should be equal when TrackingIDs are equal", c1.equals(c4));
assertTrue("Cargos should be equal when TrackingIDs are equal", c1.equals(c3));
assertTrue("Cargos should be equal when TrackingIDs are equal", c3.equals(c4));
assertFalse("Cargos are not equal when TrackingID differ", c1.equals(c2));
}
@Override
protected void setUp() throws Exception {
events = new HashSet<HandlingEvent>();
}
public void testIsUnloadedAtFinalDestination() throws Exception {
assertFalse(new Cargo().isUnloadedAtDestination());
Cargo cargo = setUpCargoWithItinerary(HANGZOU, TOKYO, NEWYORK);
assertFalse(cargo.isUnloadedAtDestination());
// Adding an event unrelated to unloading at final destination
events.add(
new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.RECEIVE, HANGZOU, null));
cargo.getEvents().addAll(events);
assertFalse(cargo.isUnloadedAtDestination());
CarrierMovement cm1 = new CarrierMovement(new CarrierMovementId("CM1"), HANGZOU, NEWYORK);
// Adding an unload event, but not at the final destination
events.add(
new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.UNLOAD, TOKYO, cm1));
cargo.getEvents().addAll(events);
assertFalse(cargo.isUnloadedAtDestination());
// Adding an event in the final destination, but not unload
events.add(
new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.CUSTOMS, NEWYORK, null));
cargo.getEvents().addAll(events);
assertFalse(cargo.isUnloadedAtDestination());
// Finally, cargo is unloaded at final destination
events.add(
new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.UNLOAD, NEWYORK, cm1));
cargo.getEvents().addAll(events);
assertTrue(cargo.isUnloadedAtDestination());
}
private Cargo populateCargoReceivedStockholm() throws Exception {
final Cargo cargo = new Cargo(trackingId("XYZ"), STOCKHOLM, MELBOURNE);
HandlingEvent he = new HandlingEvent(cargo, getDate("2007-12-01"), new DateTime(), Type.RECEIVE, STOCKHOLM, null);
events.add(he);
cargo.getEvents().addAll(events);
return cargo;
}
private Cargo populateCargoClaimedMelbourne() throws Exception {
final Cargo cargo = populateCargoOffMelbourne();
events.add(new HandlingEvent(cargo, getDate("2007-12-09"), new DateTime(), Type.CLAIM, MELBOURNE, null));
cargo.getEvents().addAll(events);
return cargo;
}
private Cargo populateCargoOffHongKong() throws Exception {
final Cargo cargo = new Cargo(trackingId("XYZ"), STOCKHOLM, MELBOURNE);
final CarrierMovement stockholmToHamburg = new CarrierMovement(
new CarrierMovementId("CAR_001"), STOCKHOLM, HAMBURG);
events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new DateTime(), Type.LOAD, STOCKHOLM, stockholmToHamburg));
events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new DateTime(), Type.UNLOAD, HAMBURG, stockholmToHamburg));
final CarrierMovement hamburgToHongKong = new CarrierMovement(
new CarrierMovementId("CAR_001"), HAMBURG, HONGKONG);
events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new DateTime(), Type.LOAD, HAMBURG, hamburgToHongKong));
events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new DateTime(), Type.UNLOAD, HONGKONG, hamburgToHongKong));
cargo.getEvents().addAll(events);
return cargo;
}
private Cargo populateCargoOnHamburg() throws Exception {
final Cargo cargo = new Cargo(trackingId("XYZ"), STOCKHOLM, MELBOURNE);
final CarrierMovement stockholmToHamburg = new CarrierMovement(
new CarrierMovementId("CAR_001"), STOCKHOLM, HAMBURG);
events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new DateTime(), Type.LOAD, STOCKHOLM, stockholmToHamburg));
events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new DateTime(), Type.UNLOAD, HAMBURG, stockholmToHamburg));
final CarrierMovement hamburgToHongKong = new CarrierMovement(
new CarrierMovementId("CAR_001"), HAMBURG, HONGKONG);
events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new DateTime(), Type.LOAD, HAMBURG, hamburgToHongKong));
cargo.getEvents().addAll(events);
return cargo;
}
private Cargo populateCargoOffMelbourne() throws Exception {
final Cargo cargo = new Cargo(trackingId("XYZ"), STOCKHOLM, MELBOURNE);
final CarrierMovement stockholmToHamburg = new CarrierMovement(
new CarrierMovementId("CAR_001"), STOCKHOLM, HAMBURG);
events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new DateTime(), Type.LOAD, STOCKHOLM, stockholmToHamburg));
events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new DateTime(), Type.UNLOAD, HAMBURG, stockholmToHamburg));
final CarrierMovement hamburgToHongKong = new CarrierMovement(
new CarrierMovementId("CAR_001"), HAMBURG, HONGKONG);
events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new DateTime(), Type.LOAD, HAMBURG, hamburgToHongKong));
events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new DateTime(), Type.UNLOAD, HONGKONG, hamburgToHongKong));
final CarrierMovement hongKongToMelbourne = new CarrierMovement(
new CarrierMovementId("CAR_001"), HONGKONG, MELBOURNE);
events.add(new HandlingEvent(cargo, getDate("2007-12-05"), new DateTime(), Type.LOAD, HONGKONG, hongKongToMelbourne));
events.add(new HandlingEvent(cargo, getDate("2007-12-07"), new DateTime(), Type.UNLOAD, MELBOURNE, hongKongToMelbourne));
cargo.getEvents().addAll(events);
return cargo;
}
private Cargo populateCargoOnHongKong() throws Exception {
final Cargo cargo = new Cargo(trackingId("XYZ"), STOCKHOLM, MELBOURNE);
final CarrierMovement stockholmToHamburg = new CarrierMovement(
new CarrierMovementId("CAR_001"), STOCKHOLM, HAMBURG);
events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new DateTime(), Type.LOAD, STOCKHOLM, stockholmToHamburg));
events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new DateTime(), Type.UNLOAD, HAMBURG, stockholmToHamburg));
final CarrierMovement hamburgToHongKong = new CarrierMovement(
new CarrierMovementId("CAR_001"), HAMBURG, HONGKONG);
events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new DateTime(), Type.LOAD, HAMBURG, hamburgToHongKong));
events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new DateTime(), Type.UNLOAD, HONGKONG, hamburgToHongKong));
final CarrierMovement hongKongToMelbourne = new CarrierMovement(
new CarrierMovementId("CAR_001"), HONGKONG, MELBOURNE);
events.add(new HandlingEvent(cargo, getDate("2007-12-05"), new DateTime(), Type.LOAD, HONGKONG, hongKongToMelbourne));
cargo.getEvents().addAll(events);
return cargo;
}
public void testIsMisdirected() throws Exception {
//A cargo with no itinerary is not misdirected
Cargo cargo = new Cargo(trackingId("TRKID"), SHANGHAI, GOTHENBURG);
assertFalse(cargo.isMisdirected());
cargo = setUpCargoWithItinerary(SHANGHAI, ROTTERDAM, GOTHENBURG);
//A cargo with no handling events is not misdirected
assertFalse(cargo.isMisdirected());
Collection<HandlingEvent> handlingEvents = new ArrayList<HandlingEvent>();
CarrierMovement abc = new CarrierMovement(new CarrierMovementId("ABC"), SHANGHAI, ROTTERDAM);
CarrierMovement def = new CarrierMovement(new CarrierMovementId("DEF"), ROTTERDAM, GOTHENBURG);
CarrierMovement ghi = new CarrierMovement(new CarrierMovementId("GHI"), ROTTERDAM, NEWYORK);
//Happy path
handlingEvents.add(new HandlingEvent(cargo, new DateTime(10), new DateTime(20), Type.RECEIVE, SHANGHAI, null));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(30), new DateTime(40), Type.LOAD, SHANGHAI, abc));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(50), new DateTime(60), Type.UNLOAD, ROTTERDAM, abc));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(70), new DateTime(80), Type.LOAD, ROTTERDAM, def));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(90), new DateTime(100), Type.UNLOAD, GOTHENBURG, def));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(110), new DateTime(120), Type.CLAIM, GOTHENBURG, null));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(130), new DateTime(140), Type.CUSTOMS, GOTHENBURG, null));
events.addAll(handlingEvents);
cargo.getEvents().addAll(events);
assertFalse(cargo.isMisdirected());
//Try a couple of failing ones
cargo = setUpCargoWithItinerary(SHANGHAI, ROTTERDAM, GOTHENBURG);
handlingEvents = new ArrayList<HandlingEvent>();
handlingEvents.add(new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.RECEIVE, HANGZOU, null));
events.addAll(handlingEvents);
cargo.getEvents().addAll(events);
assertTrue(cargo.isMisdirected());
cargo = setUpCargoWithItinerary(SHANGHAI, ROTTERDAM, GOTHENBURG);
handlingEvents = new ArrayList<HandlingEvent>();
handlingEvents.add(new HandlingEvent(cargo, new DateTime(10), new DateTime(20), Type.RECEIVE, SHANGHAI, null));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(30), new DateTime(40), Type.LOAD, SHANGHAI, abc));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(50), new DateTime(60), Type.UNLOAD, ROTTERDAM, abc));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(70), new DateTime(80), Type.LOAD, ROTTERDAM, ghi));
events.addAll(handlingEvents);
cargo.getEvents().addAll(events);
assertTrue(cargo.isMisdirected());
cargo = setUpCargoWithItinerary(SHANGHAI, ROTTERDAM, GOTHENBURG);
handlingEvents = new ArrayList<HandlingEvent>();
handlingEvents.add(new HandlingEvent(cargo, new DateTime(10), new DateTime(20), Type.RECEIVE, SHANGHAI, null));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(30), new DateTime(40), Type.LOAD, SHANGHAI, abc));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(50), new DateTime(60), Type.UNLOAD, ROTTERDAM, abc));
handlingEvents.add(new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.CLAIM, ROTTERDAM, null));
events.addAll(handlingEvents);
cargo.getEvents().addAll(events);
assertTrue(cargo.isMisdirected());
}
private Cargo setUpCargoWithItinerary(Location origin, Location midpoint, Location destination) {
Cargo cargo = new Cargo(trackingId("CARGO1"), origin, destination);
CarrierMovement cm = new CarrierMovement(
new CarrierMovementId("ABC"), origin, destination);
Itinerary itinerary = new Itinerary(
Arrays.asList(
new Leg(cm, origin, midpoint),
new Leg(cm, midpoint, destination)
)
);
cargo.attachItinerary(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 DateTime getDate(String isoFormat) throws ParseException {
final DateTimeFormatter df = DateTimeFormat.forPattern("yyyy-MM-dd");
return df.parseDateTime(isoFormat);
}
}